1/////////////////////////////////////////////////////////////////////////////
2// Name:        view.cpp
3// Purpose:     View classes
4// Author:      Julian Smart
5// Modified by:
6// Created:     04/01/98
7// RCS-ID:      $Id: view.cpp 35650 2005-09-23 12:56:45Z MR $
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#include "docview.h"
28#include "doc.h"
29#include "view.h"
30
31IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView)
32
33// For drawing lines in a canvas
34float xpos = -1;
35float ypos = -1;
36
37BEGIN_EVENT_TABLE(DrawingView, wxView)
38    EVT_MENU(DOODLE_CUT, DrawingView::OnCut)
39END_EVENT_TABLE()
40
41// What to do when a view is created. Creates actual
42// windows for displaying the view.
43bool DrawingView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
44{
45    if (!singleWindowMode)
46    {
47        // Multiple windows
48        frame = wxGetApp().CreateChildFrame(doc, this, true);
49        frame->SetTitle(_T("DrawingView"));
50
51        canvas = GetMainFrame()->CreateCanvas(this, frame);
52#ifdef __X__
53        // X seems to require a forced resize
54        int x, y;
55        frame->GetSize(&x, &y);
56        frame->SetSize(wxDefaultCoord, wxDefaultCoord, x, y);
57#endif
58        frame->Show(true);
59    }
60    else
61    {
62        // Single-window mode
63        frame = GetMainFrame();
64        canvas = GetMainFrame()->canvas;
65        canvas->view = this;
66
67        // Associate the appropriate frame with this view.
68        SetFrame(frame);
69
70        // Make sure the document manager knows that this is the
71        // current view.
72        Activate(true);
73
74        // Initialize the edit menu Undo and Redo items
75        doc->GetCommandProcessor()->SetEditMenu(((MyFrame *)frame)->editMenu);
76        doc->GetCommandProcessor()->Initialize();
77    }
78
79    return true;
80}
81
82// Sneakily gets used for default print/preview
83// as well as drawing on the screen.
84void DrawingView::OnDraw(wxDC *dc)
85{
86    dc->SetFont(*wxNORMAL_FONT);
87    dc->SetPen(*wxBLACK_PEN);
88
89    wxList::compatibility_iterator node = ((DrawingDocument *)GetDocument())->GetDoodleSegments().GetFirst();
90    while (node)
91    {
92        DoodleSegment *seg = (DoodleSegment *)node->GetData();
93        seg->Draw(dc);
94        node = node->GetNext();
95    }
96}
97
98void DrawingView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint))
99{
100    if (canvas)
101        canvas->Refresh();
102
103/* Is the following necessary?
104#ifdef __WXMSW__
105    if (canvas)
106        canvas->Refresh();
107#else
108    if (canvas)
109    {
110        wxClientDC dc(canvas);
111        dc.Clear();
112        OnDraw(& dc);
113    }
114#endif
115*/
116}
117
118// Clean up windows used for displaying the view.
119bool DrawingView::OnClose(bool deleteWindow)
120{
121    if (!GetDocument()->Close())
122        return false;
123
124    // Clear the canvas in  case we're in single-window mode,
125    // and the canvas stays.
126    canvas->ClearBackground();
127    canvas->view = (wxView *) NULL;
128    canvas = (MyCanvas *) NULL;
129
130    wxString s(wxTheApp->GetAppName());
131    if (frame)
132        frame->SetTitle(s);
133
134    SetFrame((wxFrame *) NULL);
135
136    Activate(false);
137
138    if (deleteWindow && !singleWindowMode)
139    {
140        delete frame;
141        return true;
142    }
143    return true;
144}
145
146void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) )
147{
148    DrawingDocument *doc = (DrawingDocument *)GetDocument();
149    doc->GetCommandProcessor()->Submit(new DrawingCommand(_T("Cut Last Segment"), DOODLE_CUT, doc, (DoodleSegment *) NULL));
150}
151
152IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView)
153
154bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
155{
156    frame = wxGetApp().CreateChildFrame(doc, this, false);
157
158    int width, height;
159    frame->GetClientSize(&width, &height);
160    textsw = new MyTextWindow(this, frame, wxPoint(0, 0), wxSize(width, height), wxTE_MULTILINE);
161    frame->SetTitle(_T("TextEditView"));
162
163#ifdef __X__
164    // X seems to require a forced resize
165    int x, y;
166    frame->GetSize(&x, &y);
167    frame->SetSize(wxDefaultCoord, wxDefaultCoord, x, y);
168#endif
169
170    frame->Show(true);
171    Activate(true);
172
173    return true;
174}
175
176// Handled by wxTextWindow
177void TextEditView::OnDraw(wxDC *WXUNUSED(dc) )
178{
179}
180
181void TextEditView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
182{
183}
184
185bool TextEditView::OnClose(bool deleteWindow)
186{
187    if (!GetDocument()->Close())
188        return false;
189
190    Activate(false);
191
192    if (deleteWindow)
193    {
194        delete frame;
195        return true;
196    }
197    return true;
198}
199
200/*
201* Window implementations
202*/
203
204BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
205    EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
206END_EVENT_TABLE()
207
208// Define a constructor for my canvas
209MyCanvas::MyCanvas(wxView *v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style):
210    wxScrolledWindow(frame, wxID_ANY, pos, size, style)
211{
212    view = v;
213}
214
215// Define the repainting behaviour
216void MyCanvas::OnDraw(wxDC& dc)
217{
218    if (view)
219        view->OnDraw(& dc);
220}
221
222// This implements a tiny doodling program. Drag the mouse using
223// the left button.
224void MyCanvas::OnMouseEvent(wxMouseEvent& event)
225{
226    if (!view)
227        return;
228
229    static DoodleSegment *currentSegment = (DoodleSegment *) NULL;
230
231    wxClientDC dc(this);
232    PrepareDC(dc);
233
234    dc.SetPen(*wxBLACK_PEN);
235
236    wxPoint pt(event.GetLogicalPosition(dc));
237
238    if (currentSegment && event.LeftUp())
239    {
240        if (currentSegment->lines.GetCount() == 0)
241        {
242            delete currentSegment;
243            currentSegment = (DoodleSegment *) NULL;
244        }
245        else
246        {
247            // We've got a valid segment on mouse left up, so store it.
248            DrawingDocument *doc = (DrawingDocument *)view->GetDocument();
249
250            doc->GetCommandProcessor()->Submit(new DrawingCommand(_T("Add Segment"), DOODLE_ADD, doc, currentSegment));
251
252            view->GetDocument()->Modify(true);
253            currentSegment = (DoodleSegment *) NULL;
254        }
255    }
256
257    if (xpos > -1 && ypos > -1 && event.Dragging())
258    {
259        if (!currentSegment)
260            currentSegment = new DoodleSegment;
261
262        DoodleLine *newLine = new DoodleLine;
263        newLine->x1 = (long)xpos;
264        newLine->y1 = (long)ypos;
265        newLine->x2 = pt.x;
266        newLine->y2 = pt.y;
267        currentSegment->lines.Append(newLine);
268
269        dc.DrawLine( (long)xpos, (long)ypos, pt.x, pt.y);
270    }
271    xpos = pt.x;
272    ypos = pt.y;
273}
274
275// Define a constructor for my text subwindow
276MyTextWindow::MyTextWindow(wxView *v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style):
277    wxTextCtrl(frame, wxID_ANY, _T(""), pos, size, style)
278{
279    view = v;
280}
281
282
283