]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxllist.cpp
Added wxFrame::OnCreateStatusBar and ToolBar
[wxWidgets.git] / user / wxLayout / wxllist.cpp
1 /*-*- c++ -*-********************************************************
2 * wxFTCanvas: a canvas for editing formatted text *
3 * *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
5 * *
6 * $Id$ *
7 *******************************************************************/
8
9 /*
10 - each Object knows its size and how to draw itself
11 - the list is responsible for calculating positions
12 - the draw coordinates for each object are the top left corner
13 - coordinates only get calculated when things get redrawn
14 - during redraw each line gets iterated over twice, first just
15 calculating baselines and positions, second to actually draw it
16 - the cursor position is the position before an object, i.e. if the
17 buffer starts with a text-object, cursor 0,0 is just before the
18 first character
19 */
20
21 #ifdef __GNUG__
22 #pragma implementation "wxllist.h"
23 #endif
24
25 // these two lines are for use in M:
26 //#include "Mpch.h"
27 //#include "gui/wxllist.h"
28
29 #include "wxllist.h"
30
31 #ifndef USE_PCH
32 # include "iostream.h"
33
34 # include <wx/dc.h>
35 # include <wx/postscrp.h>
36 # include <wx/print.h>
37 #endif
38
39 #define BASELINESTRETCH 12
40
41 #ifdef WXLAYOUT_DEBUG
42 static const char *_t[] = { "invalid", "text", "cmd", "icon",
43 "linebreak"};
44
45 void
46 wxLayoutObjectBase::Debug(void)
47 {
48 CoordType bl = 0;
49 cerr << _t[GetType()] << ": size=" << GetSize(&bl).x << ","
50 << GetSize(&bl).y << " bl=" << bl;
51 }
52
53 # define WXL_VAR(x) cerr << #x"=" << x << endl;
54 # define WXL_DBG_POINT(p) cerr << #p << ": " << p.x << ',' << p.y << endl
55 # define WXL_TRACE(f) cerr << #f":" << endl;
56 #else
57 # define WXL_VAR(x)
58 # define WXL_DBG_POINT(p)
59 # define WXL_TRACE(f)
60 #endif
61
62 //-------------------------- wxLayoutObjectText
63
64 wxLayoutObjectText::wxLayoutObjectText(const String &txt)
65 {
66 m_Text = txt;
67 m_Width = 0;
68 m_Height = 0;
69 }
70
71
72 wxPoint
73 wxLayoutObjectText::GetSize(CoordType *baseLine) const
74 {
75 if(baseLine) *baseLine = m_BaseLine;
76 return wxPoint(m_Width, m_Height);
77 }
78
79 void
80 wxLayoutObjectText::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
81 bool draw)
82 {
83 long descent = 0l;
84 dc.GetTextExtent(Str(m_Text),&m_Width, &m_Height, &descent);
85 //FIXME: wxGTK does not set descent to a descent value yet.
86 if(descent == 0)
87 descent = (2*m_Height)/10; // crude fix
88 m_BaseLine = m_Height - descent;
89 position.y += baseLine-m_BaseLine;
90 if(draw)
91 dc.DrawText(Str(m_Text),position.x,position.y);
92 # ifdef WXLAYOUT_DEBUG
93 // dc.DrawRectangle(position.x, position.y, m_Width, m_Height);
94 # endif
95 }
96
97 #ifdef WXLAYOUT_DEBUG
98 void
99 wxLayoutObjectText::Debug(void)
100 {
101 wxLayoutObjectBase::Debug();
102 cerr << " `" << m_Text << '\'';
103 }
104 #endif
105
106 //-------------------------- wxLayoutObjectIcon
107
108 wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon)
109 : m_Icon(icon)
110 {
111 }
112
113 void
114 wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
115 bool draw)
116 {
117 position.y += baseLine - m_Icon->GetHeight();
118 if(draw)
119 dc.DrawIcon(m_Icon,position.x,position.y);
120 }
121
122 wxPoint
123 wxLayoutObjectIcon::GetSize(CoordType *baseLine) const
124 {
125 wxASSERT(baseLine);
126 *baseLine = m_Icon->GetHeight();
127 return wxPoint(m_Icon->GetWidth(), m_Icon->GetHeight());
128 }
129
130 //-------------------------- wxLayoutObjectCmd
131
132
133 wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
134 weight, bool underline,
135 wxColour const *fg, wxColour const *bg)
136
137 {
138 m_font = new wxFont(size,family,style,weight,underline);
139 m_ColourFG = fg;
140 m_ColourBG = bg;
141 }
142
143 wxLayoutObjectCmd::~wxLayoutObjectCmd()
144 {
145 delete m_font;
146 }
147
148 wxLayoutStyleInfo *
149 wxLayoutObjectCmd::GetStyle(void) const
150 {
151 wxLayoutStyleInfo *si = new wxLayoutStyleInfo();
152
153
154 si->size = m_font->GetPointSize();
155 si->family = m_font->GetFamily();
156 si->style = m_font->GetStyle();
157 si->underline = m_font->GetUnderlined();
158 si->weight = m_font->GetWeight();
159
160 si->fg_red = m_ColourFG->Red();
161 si->fg_green = m_ColourFG->Green();
162 si->fg_blue = m_ColourFG->Blue();
163 si->bg_red = m_ColourBG->Red();
164 si->bg_green = m_ColourBG->Green();
165 si->bg_blue = m_ColourBG->Blue();
166
167 return si;
168 }
169
170 void
171 wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint position, CoordType lineHeight,
172 bool draw)
173 {
174 wxASSERT(m_font);
175 // this get called even when draw==false, so that recalculation
176 // uses right font sizes
177 dc.SetFont(m_font);
178 if(m_ColourFG)
179 dc.SetTextForeground(*m_ColourFG);
180 if(m_ColourBG)
181 dc.SetTextBackground(*m_ColourBG);
182 }
183
184 //-------------------------- wxwxLayoutList
185
186 wxLayoutList::wxLayoutList()
187 {
188 m_DefaultSetting = NULL;
189 Clear();
190 }
191
192 wxLayoutList::~wxLayoutList()
193 {
194 if(m_DefaultSetting)
195 delete m_DefaultSetting;
196 }
197
198
199 void
200 wxLayoutList::LineBreak(void)
201 {
202 Insert(new wxLayoutObjectLineBreak);
203 m_CursorPosition.x = 0; m_CursorPosition.y++;
204 }
205
206 void
207 wxLayoutList::SetFont(int family, int size, int style, int weight,
208 int underline, wxColour const *fg,
209 wxColour const *bg)
210 {
211 if(family != -1) m_FontFamily = family;
212 if(size != -1) m_FontPtSize = size;
213 if(style != -1) m_FontStyle = style;
214 if(weight != -1) m_FontWeight = weight;
215 if(underline != -1) m_FontUnderline = underline != 0;
216
217 if(fg != NULL) m_ColourFG = fg;
218 if(bg != NULL) m_ColourBG = bg;
219
220 Insert(
221 new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
222 m_ColourFG, m_ColourBG));
223 }
224
225 void
226 wxLayoutList::SetFont(int family, int size, int style, int weight,
227 int underline, char const *fg, char const *bg)
228 {
229 wxColour const
230 * cfg = NULL,
231 * cbg = NULL;
232
233 if( fg )
234 cfg = wxTheColourDatabase->FindColour(fg);
235 if( bg )
236 cbg = wxTheColourDatabase->FindColour(bg);
237
238 SetFont(family,size,style,weight,underline,cfg,cbg);
239 }
240
241
242 /// for access by wxLayoutWindow:
243 void
244 wxLayoutList::GetSize(CoordType *max_x, CoordType *max_y,
245 CoordType *lineHeight)
246 {
247 wxASSERT(max_x); wxASSERT(max_y); wxASSERT(lineHeight);
248 *max_x = m_MaxX;
249 *max_y = m_MaxY;
250 *lineHeight = m_LineHeight;
251 }
252
253 wxLayoutObjectBase *
254 wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
255 {
256 wxLayoutObjectList::iterator i;
257
258 // in case we need to look for an object
259 wxLayoutObjectBase *foundObject = NULL;
260
261 // first object in current line
262 wxLayoutObjectList::iterator headOfLine;
263
264 // do we need to recalculate current line?
265 bool recalculate = false;
266
267 // do we calculate or draw? Either true or false.
268 bool draw = false;
269 // drawing parameters:
270 wxPoint position = wxPoint(0,0);
271 wxPoint position_HeadOfLine;
272 CoordType baseLine = m_FontPtSize;
273 CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
274
275 // where to draw the cursor
276 wxPoint cursorPosition, cursorSize;
277
278 // we trace the objects' cursor positions so we can draw the cursor
279 wxPoint cursor = wxPoint(0,0);
280 // the cursor position inside the object
281 CoordType cursorOffset = 0;
282 // object under cursor
283 wxLayoutObjectList::iterator cursorObject = FindCurrentObject(&cursorOffset);
284
285 // queried from each object:
286 wxPoint size = wxPoint(0,0);
287 CoordType objBaseLine = baseLine;
288 wxLayoutObjectType type;
289
290 // used temporarily
291 wxLayoutObjectText *tobj = NULL;
292
293
294 // this is needed for printing to a printer:
295 // only interesting for printer/PS output
296 int pageWidth, pageHeight; //GetSize() still needs int at the moment
297 struct
298 {
299 int top, bottom, left, right;
300 } margins;
301
302 if(
303 #ifdef __WXMSW__
304 dc.IsKindOf(CLASSINFO(wxPrinterDC)) ||
305 #endif
306 dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
307 {
308 WXL_VAR(wxThePrintSetupData);
309
310 dc.GetSize(&pageWidth, &pageHeight);
311 dc.StartDoc(_("Printing..."));
312 dc.StartPage();
313 margins.top = (1*pageHeight)/10; // 10%
314 margins.bottom = (9*pageHeight)/10; // 90%
315 margins.left = (1*pageWidth)/10;
316 margins.right = (9*pageWidth)/10;
317 }
318 else
319 {
320 margins.top = 0; margins.left = 0;
321 margins.right = -1;
322 margins.bottom = -1;
323 }
324 position.y = margins.right;
325 position.x = margins.left;
326
327 WXL_VAR(findObject); WXL_VAR(findCoords.x); WXL_VAR(findCoords.y);
328 // if the cursorobject is a cmd, we need to find the first
329 // printable object:
330 while(cursorObject != end()
331 && (*cursorObject)->GetType() == WXLO_TYPE_CMD)
332 cursorObject++;
333
334 headOfLine = begin();
335 position_HeadOfLine = position;
336
337 // setting up the default:
338 dc.SetTextForeground( *wxBLACK );
339 dc.SetTextBackground( *wxWHITE );
340 dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background
341 dc.SetFont( *wxNORMAL_FONT );
342
343
344 //FIXME: who frees the brush, how long does it need to exist?
345 if(m_DefaultSetting)
346 m_DefaultSetting->Draw(dc,wxPoint(0,0),0,true);
347
348 // we calculate everything for drawing a line, then rewind to the
349 // begin of line and actually draw it
350 i = begin();
351 for(;;)
352 {
353 recalculate = false;
354
355 if(i == end())
356 break;
357 type = (*i)->GetType();
358
359 // to initialise sizes of objects, we need to call Draw
360 (*i)->Draw(dc, position, baseLine, draw);
361
362 // update coordinates for next object:
363 size = (*i)->GetSize(&objBaseLine);
364 if(findObject && draw) // we need to look for an object
365 {
366 if(findCoords.y >= position.y
367 && findCoords.y <= position.y+size.y
368 && findCoords.x >= position.x
369 && findCoords.x <= position.x+size.x)
370 {
371 foundObject = *i;
372 findObject = false; // speeds things up
373 }
374 }
375 // draw the cursor
376 if(m_Editable && draw && i == cursorObject)
377 {
378 if(type == WXLO_TYPE_TEXT) // special treatment
379 {
380 long descent = 0l; long width, height;
381 tobj = (wxLayoutObjectText *)*i;
382 String str = tobj->GetText();
383 WXL_VAR(m_CursorPosition.x); WXL_VAR(cursor.x);
384 str = str.substr(0, cursorOffset);
385 WXL_VAR(str);
386 dc.GetTextExtent(Str(str), &width,&height, &descent);
387 WXL_VAR(height);
388 WXL_VAR(width);
389 WXL_VAR(descent);
390 cursorPosition = wxPoint(position.x+width,
391 position.y+(baseLineSkip-height));
392 cursorSize = wxPoint(1, height);
393 //dc.DrawLine(position.x+width,
394 // position.y+(baseLineSkip-height),
395 // position.x+width, position.y+baseLineSkip);
396 }
397 else
398 {
399 if(type == WXLO_TYPE_LINEBREAK)
400 //dc.DrawLine(0, position.y+baseLineSkip, 0, position.y+2*baseLineSkip);
401 {
402 cursorPosition = wxPoint(0, position.y);
403 cursorSize = wxPoint(1,baseLineSkip);
404 }
405 else
406 {
407 cursorPosition = wxPoint(position.x, position.y);
408 cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
409 }
410 }
411 }
412
413 // calculate next object's position:
414 position.x += size.x;
415 if(position.x > m_MaxX)
416 m_MaxX = position.x;
417
418 // do we need to increase the line's height?
419 if(size.y > baseLineSkip)
420 {
421 baseLineSkip = size.y;
422 recalculate = true;
423 }
424 if(objBaseLine > baseLine)
425 {
426 baseLine = objBaseLine;
427 recalculate = true;
428 }
429
430 // now check whether we have finished handling this line:
431 if(type == WXLO_TYPE_LINEBREAK || i == tail())
432 {
433 if(recalculate) // do this line again
434 {
435 position.x = position_HeadOfLine.x;
436 i = headOfLine;
437 continue;
438 }
439
440 if(! draw) // finished calculating sizes
441 {
442 // if the this line needs to go onto a new page, we need
443 // to change pages before drawing it:
444 if(margins.bottom != -1 && position.y > margins.bottom)
445 {
446 dc.EndPage();
447 position_HeadOfLine.y = margins.top;
448 dc.StartPage();
449 }
450 // do this line again, this time drawing it
451 position = position_HeadOfLine;
452 draw = true;
453 i = headOfLine;
454 continue;
455 }
456 else // we have drawn a line, so continue calculating next one
457 draw = false;
458 }
459
460 // is it a linebreak?
461 if(type == WXLO_TYPE_LINEBREAK || i == tail())
462 {
463 position.x = margins.left;
464 position.y += baseLineSkip;
465 baseLine = m_FontPtSize;
466 objBaseLine = baseLine; // not all objects set it
467 baseLineSkip = (BASELINESTRETCH * baseLine)/10;
468 headOfLine = i;
469 headOfLine++;
470 position_HeadOfLine = position;
471 }
472 i++;
473 }
474 dc.EndDoc();
475 // draw the cursor
476 if(m_Editable)
477 {
478 dc.DrawRectangle(cursorPosition.x, cursorPosition.y,
479 cursorSize.x, cursorSize.y);
480 }
481 m_MaxY = position.y;
482 return foundObject;
483 }
484
485 #ifdef WXLAYOUT_DEBUG
486 void
487 wxLayoutList::Debug(void)
488 {
489 CoordType offs;
490 wxLayoutObjectList::iterator i;
491
492 cerr <<
493 "------------------------debug start-------------------------" << endl;
494 for(i = begin(); i != end(); i++)
495 {
496 (*i)->Debug();
497 cerr << endl;
498 }
499 cerr <<
500 "-----------------------debug end----------------------------"
501 << endl;
502 // show current object:
503 cerr << "Cursor: "
504 << m_CursorPosition.x << ','
505 << m_CursorPosition.y;
506
507 i = FindCurrentObject(&offs);
508 cerr << " line length: " << GetLineLength(i) << " ";
509 if(i == end())
510 {
511 cerr << "<<no object found>>" << endl;
512 return; // FIXME we should set cursor position to maximum allowed
513 // value then
514 }
515 if((*i)->GetType() == WXLO_TYPE_TEXT)
516 {
517 cerr << " \"" << ((wxLayoutObjectText *)(*i))->GetText() << "\", offs: "
518 << offs << endl;
519 }
520 else
521 cerr << ' ' << _t[(*i)->GetType()] << endl;
522
523 }
524 #endif
525
526 /******************** editing stuff ********************/
527
528 // don't change this, I know how to optimise this and will do it real
529 // soon (KB)
530
531 /*
532 * FindObjectCursor:
533 * Finds the object belonging to a given cursor position cpos and
534 * returns an iterator to that object and stores the relative cursor
535 * position in offset.
536 *
537 * For linebreaks, the offset can be 0=before or 1=after.
538 *
539 * If the cpos coordinates don't exist, they are modified.
540 */
541
542 wxLayoutObjectList::iterator
543 wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
544 {
545 wxPoint object = wxPoint(0,0); // runs along the objects
546 CoordType width;
547 wxLayoutObjectList::iterator i;
548
549 #ifdef WXLAYOUT_DEBUG
550 cerr << "Looking for object at " << cpos->x << ',' << cpos->y <<
551 endl;
552 #endif
553 for(i = begin(); i != end() && object.y <= cpos->y; i++)
554 {
555 width = (**i).CountPositions();
556 if(cpos->y == object.y) // a possible candidate
557 {
558 if((**i).GetType() ==WXLO_TYPE_LINEBREAK)
559 {
560 if(cpos->x == object.x)
561 {
562 *offset = 0;
563 return i;
564 }
565 *offset=1;
566 cpos->x = object.x;
567 return i;
568 }
569 if(cpos->x >= object.x && cpos->x <= object.x+width) // overlap
570 {
571 if(offset) *offset = cpos->x-object.x;
572 #ifdef WXLAYOUT_DEBUG
573 cerr << " found object at " << object.x << ',' <<
574 object.y << ", type:" << _t[(*i)->GetType()] <<endl;
575 #endif
576 return i;
577 }
578 }
579 // no overlap, increment coordinates
580 object.x += width;
581 if((**i).GetType() == WXLO_TYPE_LINEBREAK)
582 {
583 object.x = 0;
584 object.y++;
585 }
586 }
587 #ifdef WXLAYOUT_DEBUG
588 cerr << " not found" << endl;
589 #endif
590 // return last object, coordinates of that one:
591 i = tail();
592 if(i == end())
593 return i;
594 if((**i).GetType()==WXLO_TYPE_LINEBREAK)
595 {
596 if(offset)
597 *offset = (cpos->x > object.x) ? 1 : 0;
598 return i;
599 }
600 cpos->x = object.x; // would be the coordinate of next object
601 cpos->y = object.y;
602 cpos->x += width; // last object's width
603 if(*offset) *offset = cpos->x-object.x;
604 return i; // not found
605 }
606
607 wxLayoutObjectList::iterator
608 wxLayoutList::FindCurrentObject(CoordType *offset)
609 {
610 wxLayoutObjectList::iterator obj = end();
611
612 obj = FindObjectCursor(&m_CursorPosition, offset);
613 if(obj == end()) // not ideal yet
614 {
615 obj = tail();
616 if(obj != end()) // tail really exists
617 *offset = (*obj)->CountPositions(); // at the end of it
618 }
619 return obj;
620 }
621
622 void
623 wxLayoutList::MoveCursor(int dx, int dy)
624 {
625 CoordType offs, lineLength;
626 wxLayoutObjectList::iterator i;
627
628
629 if(dy > 0 && m_CursorPosition.y < m_MaxLine)
630 m_CursorPosition.y += dy;
631 else if(dy < 0 && m_CursorPosition.y > 0)
632 m_CursorPosition.y += dy; // dy is negative
633 if(m_CursorPosition.y < 0)
634 m_CursorPosition.y = 0;
635 else if (m_CursorPosition.y > m_MaxLine)
636 m_CursorPosition.y = m_MaxLine;
637
638 while(dx > 0)
639 {
640 i = FindCurrentObject(&offs);
641 lineLength = GetLineLength(i);
642 if(m_CursorPosition.x < lineLength)
643 {
644 m_CursorPosition.x ++;
645 dx--;
646 continue;
647 }
648 else
649 {
650 if(m_CursorPosition.y < m_MaxLine)
651 {
652 m_CursorPosition.y++;
653 m_CursorPosition.x = 0;
654 dx--;
655 }
656 else
657 break; // cannot move there
658 }
659 }
660 while(dx < 0)
661 {
662 if(m_CursorPosition.x > 0)
663 {
664 m_CursorPosition.x --;
665 dx++;
666 }
667 else
668 {
669 if(m_CursorPosition.y > 0)
670 {
671 m_CursorPosition.y --;
672 m_CursorPosition.x = 0;
673 i = FindCurrentObject(&offs);
674 lineLength = GetLineLength(i);
675 m_CursorPosition.x = lineLength;
676 dx++;
677 continue;
678 }
679 else
680 break; // cannot move left any more
681 }
682 }
683 // final adjustment:
684 i = FindCurrentObject(&offs);
685 lineLength = GetLineLength(i);
686 if(m_CursorPosition.x > lineLength)
687 m_CursorPosition.x = lineLength;
688
689 #ifdef WXLAYOUT_DEBUG
690 i = FindCurrentObject(&offs);
691 cerr << "Cursor: "
692 << m_CursorPosition.x << ','
693 << m_CursorPosition.y;
694
695 if(i == end())
696 {
697 cerr << "<<no object found>>" << endl;
698 return; // FIXME we should set cursor position to maximum allowed
699 // value then
700 }
701 if((*i)->GetType() == WXLO_TYPE_TEXT)
702 {
703 cerr << " \"" << ((wxLayoutObjectText *)(*i))->GetText() << "\", offs: "
704 << offs << endl;
705 }
706 else
707 cerr << ' ' << _t[(*i)->GetType()] << endl;
708 #endif
709 }
710
711 void
712 wxLayoutList::Delete(CoordType count)
713 {
714 WXL_TRACE(Delete);
715
716 if(!m_Editable)
717 return;
718
719 WXL_VAR(count);
720
721 CoordType offs;
722 wxLayoutObjectList::iterator i;
723
724 do
725 {
726 i = FindCurrentObject(&offs);
727 startover: // ugly, but easiest way to do it
728 if(i == end())
729 return; // we cannot delete anything more
730
731 /* Here we need to treat linebreaks differently.
732 If offs==0 we are before the linebreak, otherwise behind. */
733 if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
734 {
735 if(offs == 0)
736 {
737 m_MaxLine--;
738 erase(i);
739 count--;
740 continue; // we're done
741 }
742 else // delete the object behind the linebreak
743 {
744 i++; // we increment and continue as normal
745 offs=0;
746 goto startover;
747 }
748 }
749 else if((*i)->GetType() == WXLO_TYPE_TEXT)
750 {
751 wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
752 CoordType len = tobj->CountPositions();
753 // If we find the end of a text object, this means that we
754 // have to delete from the object following it.
755 if(len == offs)
756 {
757 i++;
758 offs = 0;
759 goto startover;
760 }
761 else if(len <= count) // delete this object
762 {
763 count -= len;
764 erase(i);
765 continue;
766 }
767 else
768 {
769 len = count;
770 tobj->GetText().erase(offs,len);
771 return; // we are done
772 }
773 }
774 else // all other objects: delete the object
775 {
776 CoordType len = (*i)->CountPositions();
777 erase(i); // after this, i is the iterator for the following object
778 count = count > len ? count -= len : 0;
779 }
780 }
781 while(count && i != end());
782 }
783
784 void
785 wxLayoutList::Insert(wxLayoutObjectBase *obj)
786 {
787 wxASSERT(obj);
788 CoordType offs;
789 wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
790
791 WXL_TRACE(Insert(obj));
792
793 if(i == end())
794 push_back(obj);
795 else if(offs == 0)
796 insert(i,obj);
797 // do we have to split a text object?
798 else if((*i)->GetType() == WXLO_TYPE_TEXT && offs != (*i)->CountPositions())
799 {
800 wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
801 #ifdef WXLAYOUT_DEBUG
802 cerr << "text: '" << tobj->GetText() << "'" << endl;
803 WXL_VAR(offs);
804 #endif
805 String left = tobj->GetText().substr(0,offs); // get part before cursor
806 WXL_VAR(left);
807 tobj->GetText() = tobj->GetText().substr(offs,(*i)->CountPositions()-offs); // keeps the right half
808 WXL_VAR(tobj->GetText());
809 insert(i,obj);
810 insert(i,new wxLayoutObjectText(left)); // inserts before
811 }
812 else
813 {
814 // all other cases, append after object:
815 wxLayoutObjectList::iterator j = i; // we want to apend after this object
816 j++;
817 if(j != end())
818 insert(j, obj);
819 else
820 push_back(obj);
821 }
822
823 m_CursorPosition.x += obj->CountPositions();
824 if(obj->GetType() == WXLO_TYPE_LINEBREAK)
825 m_MaxLine++;
826 }
827
828 void
829 wxLayoutList::Insert(String const &text)
830 {
831 wxLayoutObjectText *tobj = NULL;
832 WXL_TRACE(Insert(text));
833
834 if(! m_Editable)
835 return;
836
837 CoordType offs;
838 wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
839
840 if(i != end() && (*i)->GetType() == WXLO_TYPE_TEXT)
841 { // insert into an existing text object:
842 WXL_TRACE(inserting into existing object);
843 tobj = (wxLayoutObjectText *)*i ;
844 wxASSERT(tobj);
845 tobj->GetText().insert(offs,text);
846 }
847 else // check whether the previous object is text:
848 {
849 wxLayoutObjectList::iterator j = i;
850 j--;
851 WXL_TRACE(checking previous object);
852 if(0 && j != end() && (*j)->GetType() == WXLO_TYPE_TEXT)
853 {
854 tobj = (wxLayoutObjectText *)*i;
855 wxASSERT(tobj);
856 tobj->GetText()+=text;
857 }
858 else // insert a new text object
859 {
860 WXL_TRACE(creating new object);
861 Insert(new wxLayoutObjectText(text)); //FIXME not too optimal, slow
862 return; // position gets incremented in Insert(obj)
863 }
864 }
865 m_CursorPosition.x += strlen(text.c_str());
866 }
867
868 CoordType
869 wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i)
870 {
871 if(i == end())
872 return 0;
873
874 CoordType len = 0;
875
876 // search backwards for beginning of line:
877 while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
878 i--;
879 if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
880 i++;
881 // now we can start counting:
882 while(i != end() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
883 {
884 len += (*i)->CountPositions();
885 i++;
886 }
887 return len;
888 }
889
890 void
891 wxLayoutList::Clear(int family, int size, int style, int weight,
892 int underline, char const *fg, char const *bg)
893 {
894 wxLayoutObjectList::iterator i = begin();
895
896 while(i != end()) // == while valid
897 erase(i);
898
899 // set defaults
900 m_FontPtSize = size;
901 m_FontUnderline = false;
902 m_FontFamily = family;
903 m_FontStyle = style;
904 m_FontWeight = weight;
905 m_ColourFG = wxTheColourDatabase->FindColour(fg);
906 m_ColourBG = wxTheColourDatabase->FindColour(bg);
907
908 if(! m_ColourFG) m_ColourFG = wxBLACK;
909 if(! m_ColourBG) m_ColourBG = wxWHITE;
910
911 m_Position = wxPoint(0,0);
912 m_CursorPosition = wxPoint(0,0);
913 m_MaxLine = 0;
914 m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10;
915 m_MaxX = 0; m_MaxY = 0;
916
917
918 if(m_DefaultSetting)
919 delete m_DefaultSetting;
920 m_DefaultSetting = new
921 wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
922 m_FontWeight,m_FontUnderline,
923 m_ColourFG, m_ColourBG);
924 }