OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
transferbuffer.cpp
Go to the documentation of this file.
1//
2/// \file transferbuffer.cpp
3/// Safe transfer buffers
4//
5// Copyright (c) 2010 Vidar Hasfjord
6// Distributed under the OWLNext License (see http://owlnext.sourceforge.net).
7//
8
9#include <owl/pch.h>
10
11#include <owl/transferbuffer.h>
12#include <owl/validate.h>
13#include <map>
14#include <algorithm>
15
16namespace owl {
17
18namespace // Local implementation utilities
19{
20
21 //
22 /// Stores information about a bound field in a window's transfer buffer.
23 //
24 struct TFieldInfo
25 {
26 size_t Offset;
27 size_t Size;
28 };
29
30 //
31 /// Type of collection of bound controls
32 /// Public so that the class implementation can use free functions.
33 //
34 typedef std::map<TWindow*, TFieldInfo, std::less<TWindow*> > TFieldDetails; // NB! Default arg is for BC++ 5.0x compatibility.
35
36 //
37 /// Functor for find_if with TFieldDetails
38 //
39 struct TOffsetEq
40 {
41 size_t Offset;
42 TOffsetEq(size_t ofs) : Offset(ofs) {}
43
44 bool operator()(const TFieldDetails::value_type& v)
45 {return v.second.Offset == Offset;}
46 };
47
48 //
49 /// Functor for find_if with TFieldDetails
50 //
51 struct TIdEq
52 {
53 int Id;
54 TIdEq(int id) : Id(id) {}
55
56 bool operator()(const TFieldDetails::value_type& v)
57 {return v.first->GetId() == Id;}
58 };
59
60 //
61 /// Parameter type for TransferChild.
62 //
63 struct TTransferIterInfo
64 {
65 TFieldDetails* Details;
66 void* Buffer;
67 TTransferDirection Direction;
68 };
69
70 //
71 /// Calculates the field address and dispatches to the given child.
72 /// Checks that all participating children are bound to a field; throws if not.
73 /// Checks that the transferred size matches the bound field size; throws if not.
74 /// Forbids validator meddling; throws if a validator wants to override data transfer.
75 //
76 // TODO: Replace TXWindow (IDS_TRANSFERBUFFERSIZEMISMATCH) with a local exception class.
77 //
78 void TransferChild(TWindow& child, const TTransferIterInfo& t)
79 {
80 PRECONDITION(child);
81 if (!child.IsFlagSet(wfTransfer)) return; // disabled
82 if (TEdit* edit = TYPESAFE_DOWNCAST(&child, TEdit))
83 if (TValidator* v = edit->GetValidator())
84 if (v->HasOption(voTransfer)) throw TTransferBufferWindowBase::TXMeddlingValidator(*edit);
85
86 CHECK(t.Details);
87 TFieldDetails::const_iterator i = t.Details->find(&child);
88 if (i == t.Details->end()) throw TTransferBufferWindowBase::TXUnboundControl(child);
89 const TFieldInfo& f = (*i).second;
90 uint size = child.Transfer(nullptr, tdSizeData);
91 if (size != f.Size) TXWindow::Raise(&child, IDS_TRANSFERBUFFERSIZEMISMATCH);
92 if (t.Direction != tdSizeData)
93 {
94 void* field = static_cast<char*>(t.Buffer) + f.Offset;
95 uint transferred_size = child.Transfer(field, t.Direction);
96 if (transferred_size != size) TXWindow::Raise(&child, IDS_TRANSFERBUFFERSIZEMISMATCH);
97 }
98 }
99
100 //
101 /// See TXPolygamousControl.
102 //
103 tstring MakeMessageForTXPolygamousControl(TWindow& c)
104 {
106 TWindow* p = c.GetParentO();
107 s << _T("Control #") << c.GetId() << _T(" (") << GetFullTypeName(&c) << _T(") ")
108 << _T(" in window ") << GetFullTypeName(p) << _T(" ")
109 << _T(" is trying to bind to more than one field.\n\n")
110 << _T("Ensure that every control is bound to a separate field in the transfer buffer, ")
111 _T("and that TTransferBufferWindow::Bind is not called more than once for the same control.\n");
112 return s.str();
113 }
114
115 //
116 /// See TXFieldConflict.
117 //
118 tstring MakeMessageForTXFieldConflict(TWindow& c)
119 {
121 TWindow* p = c.GetParentO();
122 s << _T("Control #") << c.GetId() << _T(" (") << GetFullTypeName(&c) << _T(") ")
123 << _T(" in window ") << GetFullTypeName(p) << _T(" ")
124 << _T(" is trying to bind to an already bound field.\n\n")
125 << _T("Ensure that every control is bound to a separate field in the transfer buffer, ")
126 _T("and that TTransferBufferWindow::Bind is not called more than once for the same control.\n");
127 return s.str();
128 }
129
130 //
131 /// See TXUnboundControl.
132 //
133 tstring MakeMessageForTXUnboundControl(TWindow& c)
134 {
136 TWindow* p = c.GetParentO();
137 s << _T("Transfer requested by unbound control #")
138 << c.GetId() << _T(" (") << GetFullTypeName(&c) << _T(") ")
139 << _T(" in window ") << GetFullTypeName(p) << _T(".\n\n")
140 << _T("Use TTransferBufferWindow::Bind to bind the control to a field in the window's transfer buffer, ")
141 _T("or disable transfer for this control using TWindow::DisableTransfer.\n");
142 return s.str();
143 }
144
145 //
146 /// See TXMeddlingValidator.
147 //
148 tstring MakeMessageForTXMeddlingValidator(TEdit& c)
149 {
151 TWindow* p = c.GetParentO();
152 s << _T("Validator ") << GetFullTypeName(c.GetValidator())
153 << _T(" is meddling with the transfer of control #")
154 << c.GetId() << _T(" (") << GetFullTypeName(&c) << _T(") ")
155 << _T(" in window ") << GetFullTypeName(p) << _T(".\n\n")
156 << _T("Validators are not allowed to take part in transfers in a TTransferBufferWindow. ")
157 _T("Turn off transfer meddling for the validator by calling TValidator::UnsetOption(voTransfer). ")
158 _T("You must use a custom control if you need to transfer numeric buffer fields.\n");
159 return s.str();
160 }
161
162} // namespace
163
164//
165/// Private implementation class for TTransferBufferWindowBase
166/// Stores the buffer field associations.
167//
168class TTransferBufferWindowBase::TImpl
169{
170public:
171 TFieldDetails FieldDetails;
172};
173
177
182
187
189{
190 if (!buffer && direction != tdSizeData) return 0;
191 const auto info = TTransferIterInfo{&pimpl->FieldDetails, buffer, direction};
192 for (auto& w : GetChildren())
193 TransferChild(w, info);
194 return GetTransferBufferSize();
195}
196
197void TTransferBufferWindowBase::AssignField(TWindow& c, size_t offset, size_t size)
198{
199 PRECONDITION(size > 0);
200
201 TFieldDetails& f = pimpl->FieldDetails;
202 if (std::find_if(f.begin(), f.end(), TOffsetEq(offset)) != f.end())
203 throw TXFieldConflict(c);
204 if (std::find_if(f.begin(), f.end(), TIdEq(c.GetId())) != f.end())
205 throw TXPolygamousControl(c);
206
207 TFieldInfo info = {offset, size};
208 typedef std::pair<TFieldDetails::iterator, bool> TInsertResult;
209 TInsertResult r = f.insert(TFieldDetails::value_type(&c, info));
210 if (!r.second) throw TXPolygamousControl(c);
211
212 c.EnableTransfer();
213}
214
216 : TXOwl(MakeMessageForTXPolygamousControl(c))
217{}
218
220 : TXOwl(MakeMessageForTXFieldConflict(c))
221{}
222
224 : TXOwl(MakeMessageForTXUnboundControl(c))
225{}
226
228 : TXOwl(MakeMessageForTXMeddlingValidator(c))
229{}
230
231} // OWL namespace
#define CHECK(condition)
Definition checks.h:239
#define PRECONDITION(condition)
Definition checks.h:227
A TEdit is an interface object that represents an edit control interface element.
Definition edit.h:34
Thrown if a validator attempts to meddle with the transfer.
Thrown if a transfer is attempted with an unbound control.
Serves as the base class for safe transfer buffer windows.
void AssignField(TWindow &, size_t offset, size_t size)
Stores the field details and enables transfer for the given control.
TTransferBufferWindowBase()
Initializes the private implementation.
virtual ~TTransferBufferWindowBase()
Required for proper clean-up.
virtual uint Transfer(void *buffer, TTransferDirection direction)
TWindow override Dispatches to all the children.
virtual void TransferData(TTransferDirection direction)
TWindow override Initiates the transfer of the children data to or from the transfer buffer.
A streamable class, TValidator defines an abstract data validation object.
Definition validate.h:71
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
TWindow(TWindow *parent, LPCTSTR title=nullptr, TModule *module=nullptr)
Adds this to the child list of parent if nonzero, and calls EnableAutoCreate so that this will be cre...
Definition window.cpp:341
auto GetChildren()
Returns a TWindow::TChildrenRange that can be iterated by standard means.
Definition window.h:550
int GetId() const
Returns Attr.Id, the ID used to find the window in a specified parent's child list.
Definition window.h:1881
TWindow * GetParentO() const
Return the OWL's parent for this window.
Definition window.h:2006
void EnableTransfer()
Enables the transfer mechanism, which allows state data to be transferred between the window and a tr...
Definition window.h:1828
void * GetTransferBuffer() const
Definition window.h:785
uint GetTransferBufferSize() const
Definition window.h:786
static void Raise(TWindow *win=nullptr, uint resourceId=IDS_INVALIDWINDOW)
Creates the TXWindow exception and throws it.
Definition window.cpp:4611
#define _T(x)
Definition cygwin.h:51
TXOwl(const tstring &msg, uint resId=0)
An OWL exception with a given message for displaying and an unsigned Id that can be used for identifi...
Definition except.cpp:123
@ voTransfer
Option to perform conversion & transfer.
Definition validate.h:39
TTransferDirection
The TTransferDirection enum describes the constants that the transfer function uses to determine how ...
Definition window.h:92
@ wfTransfer
Participates in the Transfer mechanism.
Definition window.h:67
@ tdSizeData
Return the size of data transferred by the class.
Definition window.h:95
Object Windows Library (OWLNext Core).
Definition animctrl.h:22
tstring GetFullTypeName(T *w)
Helper; returns the type of a window as an tstring.
std::ostringstream tostringstream
Definition strmdefs.h:36
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
Safe transfer buffers.