]>
Commit | Line | Data |
---|---|---|
457814b5 | 1 | ///////////////////////////////////////////////////////////////////////////// |
2d1df0fc VZ |
2 | // Name: samples/docview/view.cpp |
3 | // Purpose: View classes implementation | |
457814b5 | 4 | // Author: Julian Smart |
2d1df0fc | 5 | // Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup |
457814b5 JS |
6 | // Created: 04/01/98 |
7 | // RCS-ID: $Id$ | |
2d1df0fc VZ |
8 | // Copyright: (c) 1998 Julian Smart |
9 | // (c) 2008 Vadim Zeitlin | |
2f6c54eb | 10 | // Licence: wxWindows license |
457814b5 JS |
11 | ///////////////////////////////////////////////////////////////////////////// |
12 | ||
457814b5 JS |
13 | // For compilers that support precompilation, includes "wx/wx.h". |
14 | #include "wx/wxprec.h" | |
15 | ||
16 | #ifdef __BORLANDC__ | |
2d1df0fc | 17 | #pragma hdrstop |
457814b5 JS |
18 | #endif |
19 | ||
20 | #ifndef WX_PRECOMP | |
2d1df0fc | 21 | #include "wx/wx.h" |
457814b5 JS |
22 | #endif |
23 | ||
e4b19d9b | 24 | #if !wxUSE_DOC_VIEW_ARCHITECTURE |
2d1df0fc | 25 | #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! |
457814b5 JS |
26 | #endif |
27 | ||
28 | #include "docview.h" | |
29 | #include "doc.h" | |
30 | #include "view.h" | |
31 | ||
2d1df0fc VZ |
32 | // ---------------------------------------------------------------------------- |
33 | // DrawingView implementation | |
34 | // ---------------------------------------------------------------------------- | |
457814b5 | 35 | |
2d1df0fc | 36 | IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView) |
457814b5 JS |
37 | |
38 | BEGIN_EVENT_TABLE(DrawingView, wxView) | |
2d1df0fc | 39 | EVT_MENU(wxID_CUT, DrawingView::OnCut) |
457814b5 JS |
40 | END_EVENT_TABLE() |
41 | ||
42 | // What to do when a view is created. Creates actual | |
43 | // windows for displaying the view. | |
e3e65dac | 44 | bool DrawingView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) |
457814b5 | 45 | { |
2d1df0fc VZ |
46 | MyApp& app = wxGetApp(); |
47 | if ( app.GetMode() != MyApp::Mode_Single ) | |
f6bcfd97 | 48 | { |
2d1df0fc VZ |
49 | // create a new window and canvas inside it |
50 | m_frame = app.CreateChildFrame(doc, this, true); | |
51 | m_frame->SetTitle("Drawing View"); | |
52 | ||
53 | m_canvas = new MyCanvas(this, m_frame); | |
6bdf5153 | 54 | m_frame->Show(true); |
f6bcfd97 | 55 | } |
2d1df0fc | 56 | else // single document mode |
f6bcfd97 | 57 | { |
2d1df0fc VZ |
58 | // reuse the existing window and canvas |
59 | m_frame = wxStaticCast(app.GetTopWindow(), wxFrame); | |
60 | m_canvas = app.GetMainWindowCanvas(); | |
61 | m_canvas->SetView(this); | |
6bdf5153 | 62 | |
f6bcfd97 | 63 | // Associate the appropriate frame with this view. |
6bdf5153 VZ |
64 | SetFrame(m_frame); |
65 | ||
f6bcfd97 BP |
66 | // Make sure the document manager knows that this is the |
67 | // current view. | |
f2aea0d1 | 68 | Activate(true); |
6bdf5153 | 69 | |
f6bcfd97 | 70 | // Initialize the edit menu Undo and Redo items |
2d1df0fc | 71 | doc->GetCommandProcessor()->SetEditMenu(app.GetMainWindowEditMenu()); |
f6bcfd97 BP |
72 | doc->GetCommandProcessor()->Initialize(); |
73 | } | |
6bdf5153 | 74 | |
f2aea0d1 | 75 | return true; |
457814b5 JS |
76 | } |
77 | ||
2d1df0fc VZ |
78 | // Sneakily gets used for default print/preview as well as drawing on the |
79 | // screen. | |
457814b5 JS |
80 | void DrawingView::OnDraw(wxDC *dc) |
81 | { | |
f6bcfd97 | 82 | dc->SetPen(*wxBLACK_PEN); |
6bdf5153 | 83 | |
2d1df0fc VZ |
84 | // simply draw all lines of all segments |
85 | const DoodleSegments& segments = GetDocument()->GetSegments(); | |
86 | for ( DoodleSegments::const_iterator i = segments.begin(); | |
87 | i != segments.end(); | |
88 | ++i ) | |
f6bcfd97 | 89 | { |
2d1df0fc VZ |
90 | const DoodleLines& lines = i->GetLines(); |
91 | for ( DoodleLines::const_iterator j = lines.begin(); | |
92 | j != lines.end(); | |
93 | ++j ) | |
94 | { | |
95 | const DoodleLine& line = *j; | |
96 | ||
97 | dc->DrawLine(line.x1, line.y1, line.x2, line.y2); | |
98 | } | |
f6bcfd97 | 99 | } |
457814b5 JS |
100 | } |
101 | ||
6bdf5153 VZ |
102 | DrawingDocument* DrawingView::GetDocument() |
103 | { | |
104 | return wxStaticCast(wxView::GetDocument(), DrawingDocument); | |
105 | } | |
106 | ||
e3e65dac | 107 | void DrawingView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint)) |
457814b5 | 108 | { |
2d1df0fc | 109 | if ( m_canvas ) |
6bdf5153 | 110 | m_canvas->Refresh(); |
457814b5 JS |
111 | } |
112 | ||
113 | // Clean up windows used for displaying the view. | |
114 | bool DrawingView::OnClose(bool deleteWindow) | |
115 | { | |
2d1df0fc | 116 | if ( !GetDocument()->Close() ) |
f2aea0d1 | 117 | return false; |
6bdf5153 | 118 | |
f2aea0d1 | 119 | Activate(false); |
6bdf5153 | 120 | |
2d1df0fc VZ |
121 | // Clear the canvas in single-window mode in which it stays alive |
122 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
123 | { | |
124 | m_canvas->ClearBackground(); | |
125 | m_canvas->ResetView(); | |
126 | m_canvas = NULL; | |
127 | ||
128 | if ( m_frame ) | |
129 | m_frame->SetTitle(wxTheApp->GetAppDisplayName()); | |
130 | } | |
131 | else // not single window mode | |
f6bcfd97 | 132 | { |
2d1df0fc VZ |
133 | if ( deleteWindow ) |
134 | wxDELETE(m_frame); | |
f6bcfd97 | 135 | } |
2d1df0fc VZ |
136 | |
137 | SetFrame(NULL); | |
138 | ||
f2aea0d1 | 139 | return true; |
457814b5 JS |
140 | } |
141 | ||
e3e65dac | 142 | void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) ) |
457814b5 | 143 | { |
2d1df0fc VZ |
144 | DrawingDocument * const doc = GetDocument(); |
145 | ||
146 | doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc)); | |
457814b5 JS |
147 | } |
148 | ||
2d1df0fc VZ |
149 | // ---------------------------------------------------------------------------- |
150 | // TextEditView implementation | |
151 | // ---------------------------------------------------------------------------- | |
152 | ||
457814b5 JS |
153 | IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView) |
154 | ||
4e553af1 VZ |
155 | BEGIN_EVENT_TABLE(TextEditView, wxView) |
156 | EVT_MENU(wxID_COPY, TextEditView::OnCopy) | |
157 | EVT_MENU(wxID_PASTE, TextEditView::OnPaste) | |
158 | EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll) | |
159 | END_EVENT_TABLE() | |
160 | ||
2d1df0fc | 161 | bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags)) |
457814b5 | 162 | { |
6bdf5153 | 163 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); |
2d1df0fc VZ |
164 | m_text = new wxTextCtrl(m_frame, wxID_ANY, "", |
165 | wxPoint(0, 0), m_frame->GetClientSize(), | |
166 | wxTE_MULTILINE); | |
6bdf5153 | 167 | |
2d1df0fc | 168 | m_frame->SetTitle("Text View"); |
6bdf5153 | 169 | m_frame->Show(true); |
2d1df0fc | 170 | |
f2aea0d1 | 171 | Activate(true); |
6bdf5153 | 172 | |
f2aea0d1 | 173 | return true; |
457814b5 JS |
174 | } |
175 | ||
2d1df0fc | 176 | void TextEditView::OnDraw(wxDC *WXUNUSED(dc)) |
457814b5 | 177 | { |
2d1df0fc | 178 | // nothing to do here, wxTextCtrl draws itself |
457814b5 JS |
179 | } |
180 | ||
181 | bool TextEditView::OnClose(bool deleteWindow) | |
182 | { | |
2d1df0fc | 183 | if ( !GetDocument()->Close() ) |
f2aea0d1 | 184 | return false; |
6bdf5153 | 185 | |
f2aea0d1 | 186 | Activate(false); |
6bdf5153 | 187 | |
2d1df0fc | 188 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) |
f6bcfd97 | 189 | { |
2d1df0fc | 190 | m_text->Clear(); |
f6bcfd97 | 191 | } |
2d1df0fc VZ |
192 | else // not single window mode |
193 | { | |
194 | if ( deleteWindow ) | |
195 | wxDELETE(m_frame); | |
196 | } | |
197 | ||
f2aea0d1 | 198 | return true; |
457814b5 JS |
199 | } |
200 | ||
2d1df0fc VZ |
201 | // ---------------------------------------------------------------------------- |
202 | // MyCanvas implementation | |
203 | // ---------------------------------------------------------------------------- | |
457814b5 JS |
204 | |
205 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) | |
206 | EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) | |
207 | END_EVENT_TABLE() | |
208 | ||
209 | // Define a constructor for my canvas | |
2d1df0fc VZ |
210 | MyCanvas::MyCanvas(wxView *view, wxWindow *parent) |
211 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) | |
457814b5 | 212 | { |
6bdf5153 | 213 | m_view = view; |
2d1df0fc VZ |
214 | m_currentSegment = NULL; |
215 | m_lastMousePos = wxDefaultPosition; | |
216 | ||
217 | SetCursor(wxCursor(wxCURSOR_PENCIL)); | |
218 | ||
219 | // this is completely arbitrary and is done just for illustration purposes | |
220 | SetVirtualSize(1000, 1000); | |
221 | SetScrollRate(20, 20); | |
222 | ||
223 | SetBackgroundColour(*wxWHITE); | |
224 | } | |
225 | ||
226 | MyCanvas::~MyCanvas() | |
227 | { | |
228 | delete m_currentSegment; | |
457814b5 JS |
229 | } |
230 | ||
231 | // Define the repainting behaviour | |
232 | void MyCanvas::OnDraw(wxDC& dc) | |
233 | { | |
2d1df0fc | 234 | if ( m_view ) |
6bdf5153 | 235 | m_view->OnDraw(& dc); |
457814b5 JS |
236 | } |
237 | ||
2d1df0fc VZ |
238 | // This implements a tiny doodling program. Drag the mouse using the left |
239 | // button. | |
457814b5 JS |
240 | void MyCanvas::OnMouseEvent(wxMouseEvent& event) |
241 | { | |
2d1df0fc | 242 | if ( !m_view ) |
f6bcfd97 | 243 | return; |
6bdf5153 | 244 | |
f6bcfd97 BP |
245 | wxClientDC dc(this); |
246 | PrepareDC(dc); | |
6bdf5153 | 247 | |
f6bcfd97 | 248 | dc.SetPen(*wxBLACK_PEN); |
6bdf5153 | 249 | |
2d1df0fc | 250 | const wxPoint pt(event.GetLogicalPosition(dc)); |
6bdf5153 | 251 | |
2d1df0fc VZ |
252 | // is this the end of the current segment? |
253 | if ( m_currentSegment && event.LeftUp() ) | |
457814b5 | 254 | { |
2d1df0fc | 255 | if ( !m_currentSegment->IsEmpty() ) |
f6bcfd97 BP |
256 | { |
257 | // We've got a valid segment on mouse left up, so store it. | |
2d1df0fc VZ |
258 | DrawingDocument * const |
259 | doc = wxStaticCast(m_view->GetDocument(), DrawingDocument); | |
6bdf5153 | 260 | |
2d1df0fc VZ |
261 | doc->GetCommandProcessor()->Submit( |
262 | new DrawingAddSegmentCommand(doc, *m_currentSegment)); | |
6bdf5153 | 263 | |
2d1df0fc | 264 | doc->Modify(true); |
f6bcfd97 | 265 | } |
2d1df0fc VZ |
266 | |
267 | delete m_currentSegment; | |
268 | m_currentSegment = NULL; | |
457814b5 | 269 | } |
6bdf5153 | 270 | |
2d1df0fc VZ |
271 | // is this the start of a new segment? |
272 | if ( m_lastMousePos != wxDefaultPosition && event.Dragging() ) | |
457814b5 | 273 | { |
2d1df0fc VZ |
274 | if ( !m_currentSegment ) |
275 | m_currentSegment = new DoodleSegment; | |
6bdf5153 | 276 | |
2d1df0fc | 277 | m_currentSegment->AddLine(m_lastMousePos, pt); |
6bdf5153 | 278 | |
2d1df0fc | 279 | dc.DrawLine(m_lastMousePos, pt); |
457814b5 | 280 | } |
457814b5 | 281 | |
2d1df0fc | 282 | m_lastMousePos = pt; |
457814b5 JS |
283 | } |
284 |