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 © 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 {
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);
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);
97 }
98 }
99
100 //
101 /// See TXPolygamousControl.
102 //
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 //
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 //
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 //
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). ")
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())
194 return GetTransferBufferSize();
195}
196
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
218
222
226
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 more than one control tries to associate with the same field.
Thrown if a a control tries to associate with more than one field.
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.
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
auto GetChildren()
Returns a TWindow::TChildrenRange that can be iterated by standard means.
Definition window.h:550
void * GetTransferBuffer() const
Definition window.h:785
uint GetTransferBufferSize() const
Definition window.h:786
TXOwl is root class of the ObjectWindows exception hierarchy.
Definition except.h:38
static void Raise(TWindow *win=nullptr, uint resourceId=IDS_INVALIDWINDOW)
Creates the TXWindow exception and throws it.
Definition window.cpp:4612
#define _T(x)
Definition cygwin.h:51
@ 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.