]> git.saurik.com Git - wxWidgets.git/blob - samples/docvwmdi/doc.cpp
Use type safe list for model notifiers, sample corrected
[wxWidgets.git] / samples / docvwmdi / doc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: doc.cpp
3 // Purpose: Implements document functionality
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #if !wxUSE_DOC_VIEW_ARCHITECTURE
24 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
25 #endif
26
27 #if wxUSE_STD_IOSTREAM
28 #include "wx/ioswrap.h"
29 #else
30 #include "wx/txtstrm.h"
31 #endif
32
33 #include "doc.h"
34 #include "view.h"
35
36 IMPLEMENT_DYNAMIC_CLASS(DrawingDocument, wxDocument)
37
38 DrawingDocument::~DrawingDocument(void)
39 {
40 WX_CLEAR_LIST(wxList, doodleSegments);
41 }
42
43 #if wxUSE_STD_IOSTREAM
44 wxSTD ostream& DrawingDocument::SaveObject(wxSTD ostream& stream)
45 {
46 wxDocument::SaveObject(stream);
47
48 wxInt32 n = doodleSegments.GetCount();
49 stream << n << _T('\n');
50
51 wxList::compatibility_iterator node = doodleSegments.GetFirst();
52 while (node)
53 {
54 DoodleSegment *segment = (DoodleSegment *)node->GetData();
55 segment->SaveObject(stream);
56 stream << _T('\n');
57
58 node = node->GetNext();
59 }
60
61 return stream;
62 }
63 #else
64 wxOutputStream& DrawingDocument::SaveObject(wxOutputStream& stream)
65 {
66 wxDocument::SaveObject(stream);
67
68 wxTextOutputStream text_stream( stream );
69
70 wxInt32 n = doodleSegments.GetCount();
71 text_stream << n << _T('\n');
72
73 wxList::compatibility_iterator node = doodleSegments.GetFirst();
74 while (node)
75 {
76 DoodleSegment *segment = (DoodleSegment *)node->GetData();
77 segment->SaveObject(stream);
78 text_stream << _T('\n');
79
80 node = node->GetNext();
81 }
82
83 return stream;
84 }
85 #endif
86
87 #if wxUSE_STD_IOSTREAM
88 wxSTD istream& DrawingDocument::LoadObject(wxSTD istream& stream)
89 {
90 wxDocument::LoadObject(stream);
91
92 wxInt32 n = 0;
93 stream >> n;
94
95 for (int i = 0; i < n; i++)
96 {
97 DoodleSegment *segment = new DoodleSegment;
98 segment->LoadObject(stream);
99 doodleSegments.Append(segment);
100 }
101
102 return stream;
103 }
104 #else
105 wxInputStream& DrawingDocument::LoadObject(wxInputStream& stream)
106 {
107 wxDocument::LoadObject(stream);
108
109 wxTextInputStream text_stream( stream );
110
111 wxInt32 n = 0;
112 text_stream >> n;
113
114 for (int i = 0; i < n; i++)
115 {
116 DoodleSegment *segment = new DoodleSegment;
117 segment->LoadObject(stream);
118 doodleSegments.Append(segment);
119 }
120
121 return stream;
122 }
123 #endif
124
125 DoodleSegment::DoodleSegment(const DoodleSegment& seg)
126 :wxObject()
127 {
128 wxList::compatibility_iterator node = seg.lines.GetFirst();
129 while (node)
130 {
131 DoodleLine *line = (DoodleLine *)node->GetData();
132 DoodleLine *newLine = new DoodleLine;
133 newLine->x1 = line->x1;
134 newLine->y1 = line->y1;
135 newLine->x2 = line->x2;
136 newLine->y2 = line->y2;
137
138 lines.Append(newLine);
139
140 node = node->GetNext();
141 }
142 }
143
144 DoodleSegment::~DoodleSegment(void)
145 {
146 WX_CLEAR_LIST(wxList, lines);
147 }
148
149 #if wxUSE_STD_IOSTREAM
150 wxSTD ostream& DoodleSegment::SaveObject(wxSTD ostream& stream)
151 {
152 wxInt32 n = lines.GetCount();
153 stream << n << _T('\n');
154
155 wxList::compatibility_iterator node = lines.GetFirst();
156 while (node)
157 {
158 DoodleLine *line = (DoodleLine *)node->GetData();
159 stream << line->x1 << _T(" ") <<
160 line->y1 << _T(" ") <<
161 line->x2 << _T(" ") <<
162 line->y2 << _T("\n");
163 node = node->GetNext();
164 }
165
166 return stream;
167 }
168 #else
169 wxOutputStream &DoodleSegment::SaveObject(wxOutputStream& stream)
170 {
171 wxTextOutputStream text_stream( stream );
172
173 wxInt32 n = lines.GetCount();
174 text_stream << n << _T('\n');
175
176 wxList::compatibility_iterator node = lines.GetFirst();
177 while (node)
178 {
179 DoodleLine *line = (DoodleLine *)node->GetData();
180 text_stream << line->x1 << _T(" ") <<
181 line->y1 << _T(" ") <<
182 line->x2 << _T(" ") <<
183 line->y2 << _T("\n");
184 node = node->GetNext();
185 }
186
187 return stream;
188 }
189 #endif
190
191 #if wxUSE_STD_IOSTREAM
192 wxSTD istream& DoodleSegment::LoadObject(wxSTD istream& stream)
193 {
194 wxInt32 n = 0;
195 stream >> n;
196
197 for (int i = 0; i < n; i++)
198 {
199 DoodleLine *line = new DoodleLine;
200 stream >> line->x1 >>
201 line->y1 >>
202 line->x2 >>
203 line->y2;
204 lines.Append(line);
205 }
206
207 return stream;
208 }
209 #else
210 wxInputStream &DoodleSegment::LoadObject(wxInputStream& stream)
211 {
212 wxTextInputStream text_stream( stream );
213
214 wxInt32 n = 0;
215 text_stream >> n;
216
217 for (int i = 0; i < n; i++)
218 {
219 DoodleLine *line = new DoodleLine;
220 text_stream >> line->x1 >>
221 line->y1 >>
222 line->x2 >>
223 line->y2;
224 lines.Append(line);
225 }
226
227 return stream;
228 }
229 #endif
230 void DoodleSegment::Draw(wxDC *dc)
231 {
232 wxList::compatibility_iterator node = lines.GetFirst();
233 while (node)
234 {
235 DoodleLine *line = (DoodleLine *)node->GetData();
236 dc->DrawLine(line->x1, line->y1, line->x2, line->y2);
237 node = node->GetNext();
238 }
239 }
240
241 /*
242 * Implementation of drawing command
243 */
244
245 DrawingCommand::DrawingCommand(const wxString& name, int command, DrawingDocument *ddoc, DoodleSegment *seg):
246 wxCommand(true, name)
247 {
248 doc = ddoc;
249 segment = seg;
250 cmd = command;
251 }
252
253 DrawingCommand::~DrawingCommand(void)
254 {
255 if (segment)
256 delete segment;
257 }
258
259 bool DrawingCommand::Do(void)
260 {
261 switch (cmd)
262 {
263 case DOODLE_CUT:
264 {
265 // Cut the last segment
266 if (doc->GetDoodleSegments().GetCount() > 0)
267 {
268 wxList::compatibility_iterator node = doc->GetDoodleSegments().GetLast();
269 if (segment)
270 delete segment;
271
272 segment = (DoodleSegment *)node->GetData();
273 doc->GetDoodleSegments().Erase(node);
274
275 doc->Modify(true);
276 doc->UpdateAllViews();
277 }
278 break;
279 }
280 case DOODLE_ADD:
281 {
282 doc->GetDoodleSegments().Append(new DoodleSegment(*segment));
283 doc->Modify(true);
284 doc->UpdateAllViews();
285 break;
286 }
287 }
288 return true;
289 }
290
291 bool DrawingCommand::Undo(void)
292 {
293 switch (cmd)
294 {
295 case DOODLE_CUT:
296 {
297 // Paste the segment
298 if (segment)
299 {
300 doc->GetDoodleSegments().Append(segment);
301 doc->Modify(true);
302 doc->UpdateAllViews();
303 segment = (DoodleSegment *) NULL;
304 }
305 doc->Modify(true);
306 doc->UpdateAllViews();
307 break;
308 }
309 case DOODLE_ADD:
310 {
311 // Cut the last segment
312 if (doc->GetDoodleSegments().GetCount() > 0)
313 {
314 wxList::compatibility_iterator node = doc->GetDoodleSegments().GetLast();
315 DoodleSegment *seg = (DoodleSegment *)node->GetData();
316 delete seg;
317 doc->GetDoodleSegments().Erase(node);
318
319 doc->Modify(true);
320 doc->UpdateAllViews();
321 }
322 }
323 }
324 return true;
325 }
326
327 IMPLEMENT_DYNAMIC_CLASS(TextEditDocument, wxDocument)
328
329 // Since text windows have their own method for saving to/loading from files,
330 // we override OnSave/OpenDocument instead of Save/LoadObject
331 bool TextEditDocument::OnSaveDocument(const wxString& filename)
332 {
333 TextEditView *view = (TextEditView *)GetFirstView();
334
335 if (!view->textsw->SaveFile(filename))
336 return false;
337 Modify(false);
338 return true;
339 }
340
341 bool TextEditDocument::OnOpenDocument(const wxString& filename)
342 {
343 TextEditView *view = (TextEditView *)GetFirstView();
344 if (!view->textsw->LoadFile(filename))
345 return false;
346
347 SetFilename(filename, true);
348 Modify(false);
349 UpdateAllViews();
350 return true;
351 }
352
353 bool TextEditDocument::IsModified(void) const
354 {
355 TextEditView *view = (TextEditView *)GetFirstView();
356 if (view)
357 {
358 return (wxDocument::IsModified() || view->textsw->IsModified());
359 }
360 else
361 return wxDocument::IsModified();
362 }
363
364 void TextEditDocument::Modify(bool mod)
365 {
366 TextEditView *view = (TextEditView *)GetFirstView();
367
368 wxDocument::Modify(mod);
369
370 if (!mod && view && view->textsw)
371 view->textsw->DiscardEdits();
372 }