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