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"
38IMPLEMENT_DYNAMIC_CLASS(DrawingDocument, wxDocument)
39
40DrawingDocument::~DrawingDocument(void)
41{
42    WX_CLEAR_LIST(wxList, doodleSegments);
43}
44
45#if wxUSE_STD_IOSTREAM
46wxSTD 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
66wxOutputStream& 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
90wxSTD 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
107wxInputStream& 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
127DoodleSegment::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
145DoodleSegment::~DoodleSegment(void)
146{
147    WX_CLEAR_LIST(wxList, lines);
148}
149
150#if wxUSE_STD_IOSTREAM
151wxSTD 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
170wxOutputStream &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
193wxSTD 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
211wxInputStream &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
232void 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
247DrawingCommand::DrawingCommand(const wxString& name, int command, DrawingDocument *ddoc, DoodleSegment *seg):
248wxCommand(true, name)
249{
250    doc = ddoc;
251    segment = seg;
252    cmd = command;
253}
254
255DrawingCommand::~DrawingCommand(void)
256{
257    if (segment)
258        delete segment;
259}
260
261bool 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
293bool 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
329IMPLEMENT_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
333bool 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
343bool 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
352bool 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
363void 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