]>
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 | |
526954c5 | 10 | // Licence: wxWindows licence |
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 | ||
f37f49b6 | 107 | void DrawingView::OnUpdate(wxView* sender, wxObject* hint) |
457814b5 | 108 | { |
f37f49b6 | 109 | wxView::OnUpdate(sender, hint); |
2d1df0fc | 110 | if ( m_canvas ) |
6bdf5153 | 111 | m_canvas->Refresh(); |
457814b5 JS |
112 | } |
113 | ||
114 | // Clean up windows used for displaying the view. | |
115 | bool DrawingView::OnClose(bool deleteWindow) | |
116 | { | |
2d1df0fc | 117 | if ( !GetDocument()->Close() ) |
f2aea0d1 | 118 | return false; |
6bdf5153 | 119 | |
f2aea0d1 | 120 | Activate(false); |
6bdf5153 | 121 | |
2d1df0fc VZ |
122 | // Clear the canvas in single-window mode in which it stays alive |
123 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
124 | { | |
125 | m_canvas->ClearBackground(); | |
126 | m_canvas->ResetView(); | |
127 | m_canvas = NULL; | |
128 | ||
129 | if ( m_frame ) | |
130 | m_frame->SetTitle(wxTheApp->GetAppDisplayName()); | |
131 | } | |
132 | else // not single window mode | |
f6bcfd97 | 133 | { |
2d1df0fc VZ |
134 | if ( deleteWindow ) |
135 | wxDELETE(m_frame); | |
f6bcfd97 | 136 | } |
2d1df0fc VZ |
137 | |
138 | SetFrame(NULL); | |
139 | ||
f2aea0d1 | 140 | return true; |
457814b5 JS |
141 | } |
142 | ||
e3e65dac | 143 | void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) ) |
457814b5 | 144 | { |
2d1df0fc VZ |
145 | DrawingDocument * const doc = GetDocument(); |
146 | ||
147 | doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc)); | |
457814b5 JS |
148 | } |
149 | ||
2d1df0fc VZ |
150 | // ---------------------------------------------------------------------------- |
151 | // TextEditView implementation | |
152 | // ---------------------------------------------------------------------------- | |
153 | ||
457814b5 JS |
154 | IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView) |
155 | ||
4e553af1 VZ |
156 | BEGIN_EVENT_TABLE(TextEditView, wxView) |
157 | EVT_MENU(wxID_COPY, TextEditView::OnCopy) | |
158 | EVT_MENU(wxID_PASTE, TextEditView::OnPaste) | |
159 | EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll) | |
160 | END_EVENT_TABLE() | |
161 | ||
2d1df0fc | 162 | bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags)) |
457814b5 | 163 | { |
6bdf5153 | 164 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); |
2d1df0fc VZ |
165 | m_text = new wxTextCtrl(m_frame, wxID_ANY, "", |
166 | wxPoint(0, 0), m_frame->GetClientSize(), | |
167 | wxTE_MULTILINE); | |
6bdf5153 | 168 | |
2d1df0fc | 169 | m_frame->SetTitle("Text View"); |
6bdf5153 | 170 | m_frame->Show(true); |
2d1df0fc | 171 | |
f2aea0d1 | 172 | Activate(true); |
6bdf5153 | 173 | |
f2aea0d1 | 174 | return true; |
457814b5 JS |
175 | } |
176 | ||
2d1df0fc | 177 | void TextEditView::OnDraw(wxDC *WXUNUSED(dc)) |
457814b5 | 178 | { |
2d1df0fc | 179 | // nothing to do here, wxTextCtrl draws itself |
457814b5 JS |
180 | } |
181 | ||
182 | bool TextEditView::OnClose(bool deleteWindow) | |
183 | { | |
2d1df0fc | 184 | if ( !GetDocument()->Close() ) |
f2aea0d1 | 185 | return false; |
6bdf5153 | 186 | |
f2aea0d1 | 187 | Activate(false); |
6bdf5153 | 188 | |
2d1df0fc | 189 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) |
f6bcfd97 | 190 | { |
2d1df0fc | 191 | m_text->Clear(); |
f6bcfd97 | 192 | } |
2d1df0fc VZ |
193 | else // not single window mode |
194 | { | |
195 | if ( deleteWindow ) | |
196 | wxDELETE(m_frame); | |
197 | } | |
198 | ||
f2aea0d1 | 199 | return true; |
457814b5 JS |
200 | } |
201 | ||
2d1df0fc VZ |
202 | // ---------------------------------------------------------------------------- |
203 | // MyCanvas implementation | |
204 | // ---------------------------------------------------------------------------- | |
457814b5 JS |
205 | |
206 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) | |
207 | EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) | |
208 | END_EVENT_TABLE() | |
209 | ||
210 | // Define a constructor for my canvas | |
2d1df0fc VZ |
211 | MyCanvas::MyCanvas(wxView *view, wxWindow *parent) |
212 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) | |
457814b5 | 213 | { |
6bdf5153 | 214 | m_view = view; |
2d1df0fc VZ |
215 | m_currentSegment = NULL; |
216 | m_lastMousePos = wxDefaultPosition; | |
217 | ||
218 | SetCursor(wxCursor(wxCURSOR_PENCIL)); | |
219 | ||
220 | // this is completely arbitrary and is done just for illustration purposes | |
221 | SetVirtualSize(1000, 1000); | |
222 | SetScrollRate(20, 20); | |
223 | ||
224 | SetBackgroundColour(*wxWHITE); | |
225 | } | |
226 | ||
227 | MyCanvas::~MyCanvas() | |
228 | { | |
229 | delete m_currentSegment; | |
457814b5 JS |
230 | } |
231 | ||
232 | // Define the repainting behaviour | |
233 | void MyCanvas::OnDraw(wxDC& dc) | |
234 | { | |
2d1df0fc | 235 | if ( m_view ) |
6bdf5153 | 236 | m_view->OnDraw(& dc); |
457814b5 JS |
237 | } |
238 | ||
2d1df0fc VZ |
239 | // This implements a tiny doodling program. Drag the mouse using the left |
240 | // button. | |
457814b5 JS |
241 | void MyCanvas::OnMouseEvent(wxMouseEvent& event) |
242 | { | |
2d1df0fc | 243 | if ( !m_view ) |
f6bcfd97 | 244 | return; |
6bdf5153 | 245 | |
f6bcfd97 BP |
246 | wxClientDC dc(this); |
247 | PrepareDC(dc); | |
6bdf5153 | 248 | |
f6bcfd97 | 249 | dc.SetPen(*wxBLACK_PEN); |
6bdf5153 | 250 | |
2d1df0fc | 251 | const wxPoint pt(event.GetLogicalPosition(dc)); |
6bdf5153 | 252 | |
2d1df0fc VZ |
253 | // is this the end of the current segment? |
254 | if ( m_currentSegment && event.LeftUp() ) | |
457814b5 | 255 | { |
2d1df0fc | 256 | if ( !m_currentSegment->IsEmpty() ) |
f6bcfd97 BP |
257 | { |
258 | // We've got a valid segment on mouse left up, so store it. | |
2d1df0fc VZ |
259 | DrawingDocument * const |
260 | doc = wxStaticCast(m_view->GetDocument(), DrawingDocument); | |
6bdf5153 | 261 | |
2d1df0fc VZ |
262 | doc->GetCommandProcessor()->Submit( |
263 | new DrawingAddSegmentCommand(doc, *m_currentSegment)); | |
6bdf5153 | 264 | |
2d1df0fc | 265 | doc->Modify(true); |
f6bcfd97 | 266 | } |
2d1df0fc | 267 | |
5276b0a5 | 268 | wxDELETE(m_currentSegment); |
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 | ||
f37f49b6 | 285 | // ---------------------------------------------------------------------------- |
2d4a03f8 | 286 | // ImageCanvas implementation |
f37f49b6 JS |
287 | // ---------------------------------------------------------------------------- |
288 | ||
f37f49b6 | 289 | // Define a constructor for my canvas |
2d4a03f8 | 290 | ImageCanvas::ImageCanvas(wxView* view, wxWindow* parent) |
f37f49b6 JS |
291 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) |
292 | { | |
2d4a03f8 VZ |
293 | SetScrollRate( 10, 10 ); |
294 | ||
f37f49b6 JS |
295 | m_view = view; |
296 | } | |
297 | ||
298 | // Define the repainting behaviour | |
2d4a03f8 | 299 | void ImageCanvas::OnDraw(wxDC& dc) |
f37f49b6 JS |
300 | { |
301 | if ( m_view ) | |
302 | m_view->OnDraw(& dc); | |
303 | } | |
304 | ||
305 | // ---------------------------------------------------------------------------- | |
2d4a03f8 | 306 | // ImageView implementation |
f37f49b6 JS |
307 | // ---------------------------------------------------------------------------- |
308 | ||
2d4a03f8 | 309 | IMPLEMENT_DYNAMIC_CLASS(ImageView, wxView) |
f37f49b6 | 310 | |
2d4a03f8 | 311 | ImageDocument* ImageView::GetDocument() |
f37f49b6 | 312 | { |
2d4a03f8 | 313 | return wxStaticCast(wxView::GetDocument(), ImageDocument); |
f37f49b6 JS |
314 | } |
315 | ||
2d4a03f8 | 316 | bool ImageView::OnCreate(wxDocument* doc, long WXUNUSED(flags)) |
f37f49b6 JS |
317 | { |
318 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); | |
319 | m_frame->SetTitle("Image View"); | |
2d4a03f8 | 320 | m_canvas = new ImageCanvas(this, m_frame); |
f37f49b6 JS |
321 | m_frame->Show(true); |
322 | Activate(true); | |
323 | return true; | |
324 | } | |
325 | ||
2d4a03f8 | 326 | void ImageView::OnUpdate(wxView* sender, wxObject* hint) |
f37f49b6 JS |
327 | { |
328 | wxView::OnUpdate(sender, hint); | |
2d4a03f8 VZ |
329 | wxImage image = GetDocument()->GetImage(); |
330 | if ( image.IsOk() ) | |
f37f49b6 | 331 | { |
2d4a03f8 | 332 | m_canvas->SetVirtualSize(image.GetWidth(), image.GetHeight()); |
f37f49b6 JS |
333 | } |
334 | } | |
335 | ||
2d4a03f8 | 336 | void ImageView::OnDraw(wxDC* dc) |
f37f49b6 | 337 | { |
2d4a03f8 VZ |
338 | wxImage image = GetDocument()->GetImage(); |
339 | if ( image.IsOk() ) | |
f37f49b6 | 340 | { |
2d4a03f8 | 341 | dc->DrawBitmap(wxBitmap(image), 0, 0); |
f37f49b6 JS |
342 | } |
343 | } | |
344 | ||
2d4a03f8 | 345 | bool ImageView::OnClose(bool deleteWindow) |
f37f49b6 JS |
346 | { |
347 | if ( !GetDocument()->Close() ) | |
348 | return false; | |
349 | ||
350 | Activate(false); | |
351 | ||
352 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
353 | { | |
354 | GetDocument()->DeleteContents(); | |
355 | } | |
356 | else // not single window mode | |
357 | { | |
358 | if ( deleteWindow ) | |
359 | wxDELETE(m_frame); | |
360 | } | |
361 | return true; | |
362 | } | |
363 |