]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxlwindow.cpp
fixes
[wxWidgets.git] / user / wxLayout / wxlwindow.cpp
1 /*-*- c++ -*-********************************************************
2 * wxLwindow.h : a scrolled Window for displaying/entering rich text*
3 * *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
5 * *
6 * $Id$
7 *******************************************************************/
8
9 #ifdef __GNUG__
10 # pragma implementation "wxlwindow.h"
11 #endif
12
13 //#include "Mpch.h"
14
15 #ifdef M_BASEDIR
16 # ifndef USE_PCH
17 # include "Mcommon.h"
18 # include "gui/wxMenuDefs.h"
19 # endif // USE_PCH
20 # include "gui/wxlwindow.h"
21 #else
22 # ifdef __WXMSW__
23 # include <windows.h>
24
25 # undef FindWindow
26 # undef GetCharWidth
27 # undef StartDoc
28 # endif
29
30 # include "wxlwindow.h"
31 # define TRACEMESSAGE(x)
32 #endif
33 # define WXL_VAR(x) cerr << #x " = " << x ;
34
35 BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
36 EVT_PAINT (wxLayoutWindow::OnPaint)
37 EVT_CHAR (wxLayoutWindow::OnChar)
38
39 EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick)
40 EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick)
41 EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick)
42 EVT_MENU(WXLOWIN_MENU_LARGER, wxLayoutWindow::OnMenu)
43 EVT_MENU(WXLOWIN_MENU_SMALLER, wxLayoutWindow::OnMenu)
44 EVT_MENU(WXLOWIN_MENU_UNDERLINE, wxLayoutWindow::OnMenu)
45 EVT_MENU(WXLOWIN_MENU_BOLD, wxLayoutWindow::OnMenu)
46 EVT_MENU(WXLOWIN_MENU_ITALICS, wxLayoutWindow::OnMenu)
47 EVT_MENU(WXLOWIN_MENU_ROMAN, wxLayoutWindow::OnMenu)
48 EVT_MENU(WXLOWIN_MENU_TYPEWRITER, wxLayoutWindow::OnMenu)
49 EVT_MENU(WXLOWIN_MENU_SANSSERIF, wxLayoutWindow::OnMenu)
50 END_EVENT_TABLE()
51
52 wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
53 : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
54 wxHSCROLL | wxVSCROLL | wxBORDER)
55
56 {
57 m_ScrollbarsSet = false;
58 m_doSendEvents = false;
59 m_ViewStartX = 0; m_ViewStartY = 0;
60 m_DoPopupMenu = true;
61 m_PopupMenu = NULL;
62
63 CoordType
64 max_x, max_y, lineHeight;
65 m_llist.GetSize(&max_x, &max_y, &lineHeight);
66 SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1);
67 EnableScrolling(true,true);
68 }
69
70 #ifdef __WXMSW__
71 long
72 wxLayoutWindow::MSWGetDlgCode()
73 {
74 // if we don't return this, we won't get OnChar() events
75 return DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTMESSAGE;
76 }
77 #endif //MSW
78
79 void
80 wxLayoutWindow::Update(void)
81 {
82 wxClientDC dc(this);
83 PrepareDC(dc);
84 if(IsDirty())
85 {
86 DoPaint(dc);
87 UpdateScrollbars();
88 ResetDirty();
89 }
90 m_llist.DrawCursor(dc);
91 }
92
93 void
94 wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
95 {
96 if(!m_doSendEvents) // nothing to do
97 return;
98
99 wxPaintDC dc( this );
100 PrepareDC( dc );
101 SetFocus();
102
103 wxPoint findPos;
104 findPos.x = dc.DeviceToLogicalX(event.GetX());
105 findPos.y = dc.DeviceToLogicalY(event.GetY());
106
107 TRACEMESSAGE(("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
108 event.GetX(), event.GetY(), findPos.x, findPos.y));
109
110 if(eventId == WXLOWIN_MENU_RCLICK && m_DoPopupMenu && m_llist.IsEditable())
111 {
112 // when does this menu get freed?
113 // how do we handle toggling? FIXME
114 PopupMenu(MakeFormatMenu(), event.GetX(), event.GetY());
115 return;
116 }
117 // find the object at this position
118 wxLayoutObjectBase *obj = m_llist.Find(findPos);
119 if(obj)
120 {
121 wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, eventId);
122 commandEvent.SetEventObject( this );
123 commandEvent.SetClientData((char *)obj);
124 GetEventHandler()->ProcessEvent(commandEvent);
125 }
126 }
127
128 /*
129 * some simple keyboard handling
130 */
131 void
132 wxLayoutWindow::OnChar(wxKeyEvent& event)
133 {
134 if(! m_llist.IsEditable()) // do nothing
135 {
136 event.Skip();
137 return;
138 }
139
140 long keyCode = event.KeyCode();
141 wxPoint p;
142 CoordType help;
143
144 switch(event.KeyCode())
145 {
146 case WXK_RIGHT:
147 m_llist.MoveCursor(1);
148 break;
149 case WXK_LEFT:
150 m_llist.MoveCursor(-1);
151 break;
152 case WXK_UP:
153 m_llist.MoveCursor(0,-1);
154 break;
155 case WXK_DOWN:
156 m_llist.MoveCursor(0,1);
157 break;
158 case WXK_PRIOR:
159 m_llist.MoveCursor(0,-20);
160 break;
161 case WXK_NEXT:
162 m_llist.MoveCursor(0,20);
163 break;
164 case WXK_HOME:
165 p = m_llist.GetCursor();
166 p.x = 0;
167 m_llist.SetCursor(p);
168 break;
169 case WXK_END:
170 p = m_llist.GetCursor();
171 p.x = m_llist.GetLineLength(m_llist.FindCurrentObject(NULL));
172 m_llist.SetCursor(p);
173 break;
174 case WXK_DELETE :
175 if(event.ControlDown()) // delete to end of line
176 {
177 help = m_llist.GetLineLength(
178 m_llist.FindCurrentObject(NULL))
179 - m_llist.GetCursor().x;
180 m_llist.Delete(help ? help : 1);
181 }
182 else
183 m_llist.Delete(1);
184 break;
185 case WXK_BACK: // backspace
186 if(m_llist.MoveCursor(-1)) {
187 m_llist.Delete(1);
188 }
189 break;
190 case WXK_RETURN:
191 m_llist.LineBreak();
192 break;
193
194 #ifdef WXLAYOUT_DEBUG
195 case WXK_F1:
196 m_llist.Debug();
197 break;
198 #endif
199
200 default:
201 if(keyCode < 256 && keyCode >= 32)
202 {
203 String tmp;
204 tmp += keyCode;
205 m_llist.Insert(tmp);
206 }
207 break;
208 }
209
210 /** Scroll so that cursor is visible! */
211 int x0,y0,x1,y1,ux,uy;
212 ViewStart(&x0,&y0);
213 GetScrollPixelsPerUnit(&ux,&uy);
214 x0*=ux; y0*=uy;
215 GetClientSize(&x1,&y1);
216
217 wxPoint cc = m_llist.GetCursorCoords();
218 int nx = x0, ny = y0;
219 // when within 10% of borders, scroll to center
220 if(cc.y > y0+(9*y1)/10)
221 ny = cc.y - y1/5;
222 else if (cc.y < y0+y1/10)
223 {
224 ny = cc.y-y1/2;
225 if(ny < 0) ny = 0;
226 }
227 if(cc.x > x0+(9*x1)/10)
228 nx = cc.x - x1/5;
229 else if (cc.x < x0+x1/10)
230 {
231 nx = cc.x-x1/2;
232 if(nx < 0) nx = 0;
233 }
234 Scroll(nx,ny);
235
236 Update();
237 }
238
239 void
240 wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
241 {
242 wxPaintDC dc( this );
243 PrepareDC( dc );
244
245 DoPaint(dc);
246
247 // wxGTK: wxMemoryDC broken?
248 #if 0
249 int x0,y0,x1,y1;
250 ViewStart(&x0,&y0);
251 GetSize(&x1,&y1);
252 WXL_VAR(x0); WXL_VAR(y0);
253 WXL_VAR(x1); WXL_VAR(y1);
254
255 wxMemoryDC(memdc);
256 wxBitmap bm(x1,y1);
257 memdc.SelectObject(bm);
258
259 // make temporary copy and edit this
260 memdc.SetDeviceOrigin(x0,y0);
261 memdc.Blit(x0,y0,x1,y1,&dc,x0,y0,wxCOPY,FALSE);
262 DoPaint(memdc);
263 // blit it back
264 dc.Blit(x0,y0,x1,y1,&memdc,x0,y0,wxCOPY,FALSE);
265 #endif
266
267 }
268
269 // does the actual painting
270 void
271 wxLayoutWindow::DoPaint(wxDC &dc)
272 {
273 m_llist.EraseAndDraw(dc);
274 m_llist.DrawCursor(dc);
275 // FIXME: not strictly correct, this does only work for changes behind
276 // the cursor position, not complete redraws
277
278 if(! m_ScrollbarsSet)
279 {
280 m_ScrollbarsSet = true; // avoid recursion
281 UpdateScrollbars();
282 }
283 }
284
285 void
286 wxLayoutWindow::UpdateScrollbars(void)
287 {
288 CoordType
289 max_x, max_y, lineHeight;
290
291 ViewStart(&m_ViewStartX, &m_ViewStartY);
292 m_llist.GetSize(&max_x, &max_y, &lineHeight);
293 SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1,m_ViewStartX,m_ViewStartY,true);
294 //EnableScrolling(true,true);
295 //Scroll(m_ViewStartX, m_ViewStartY);
296 }
297
298 void
299 wxLayoutWindow::Print(void)
300 {
301 wxPostScriptDC dc("layout.ps",true,this);
302 if (dc.Ok() && dc.StartDoc((char *)_("Printing message...")))
303 {
304 //dc.SetUserScale(1.0, 1.0);
305 m_llist.Draw(dc);
306 dc.EndDoc();
307 }
308 }
309
310 wxMenu *
311 wxLayoutWindow::MakeFormatMenu()
312 {
313 if(m_PopupMenu)
314 return m_PopupMenu;
315
316 wxMenu *m = new wxMenu();
317
318 m->Append(WXLOWIN_MENU_LARGER ,_("&Larger"),_("Switch to larger font."), false);
319 m->Append(WXLOWIN_MENU_SMALLER ,_("&Smaller"),_("Switch to smaller font."), false);
320 m->AppendSeparator();
321 m->Append(WXLOWIN_MENU_UNDERLINE,_("&Underline"),_("Toggle underline mode."), true);
322 m->Append(WXLOWIN_MENU_BOLD ,_("&Bold"),_("Toggle bold mode."), true);
323 m->Append(WXLOWIN_MENU_ITALICS ,_("&Italics"),_("Toggle italics mode."), true);
324 m->AppendSeparator();
325 m->Append(WXLOWIN_MENU_ROMAN ,_("&Roman"),_("Toggle underline mode."), false);
326 m->Append(WXLOWIN_MENU_TYPEWRITER,_("&Typewriter"),_("Toggle bold mode."), false);
327 m->Append(WXLOWIN_MENU_SANSSERIF ,_("&Sans Serif"),_("Toggle italics mode."), false);
328
329 return m_PopupMenu = m;
330 }
331
332 void wxLayoutWindow::OnMenu(wxCommandEvent& event)
333 {
334 if(! m_llist.IsEditable())
335 return;
336
337 switch (event.GetId())
338 {
339 case WXLOWIN_MENU_LARGER:
340 m_llist.SetFontLarger();
341 break;
342 case WXLOWIN_MENU_SMALLER:
343 m_llist.SetFontSmaller();
344 break;
345 case WXLOWIN_MENU_UNDERLINE:
346 m_llist.SetFontUnderline(
347 m_PopupMenu->IsChecked(WXLOWIN_MENU_UNDERLINE) ? false : true
348 );
349 break;
350 case WXLOWIN_MENU_BOLD:
351 m_llist.SetFontWeight(
352 m_PopupMenu->IsChecked(WXLOWIN_MENU_BOLD) ? wxNORMAL : wxBOLD
353 );
354 case WXLOWIN_MENU_ITALICS:
355 m_llist.SetFontStyle(
356 m_PopupMenu->IsChecked(WXLOWIN_MENU_ITALICS) ? wxNORMAL : wxITALIC
357 );
358 break;
359 case WXLOWIN_MENU_ROMAN:
360 m_llist.SetFontFamily(wxROMAN); break;
361 case WXLOWIN_MENU_TYPEWRITER:
362 m_llist.SetFontFamily(wxFIXED); break;
363 case WXLOWIN_MENU_SANSSERIF:
364 m_llist.SetFontFamily(wxSWISS); break;
365 }
366 }