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