]> git.saurik.com Git - wxWidgets.git/commitdiff
Rewrite. Cursor handling better, split Layout() and Draw(), faster.
authorKarsten Ballüder <ballueder@usa.net>
Sat, 24 Oct 1998 18:08:20 +0000 (18:08 +0000)
committerKarsten Ballüder <ballueder@usa.net>
Sat, 24 Oct 1998 18:08:20 +0000 (18:08 +0000)
Printing almost works.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@906 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

user/wxLayout/wxLayout.cpp
user/wxLayout/wxllist.cpp
user/wxLayout/wxllist.h
user/wxLayout/wxlparser.cpp
user/wxLayout/wxlwindow.cpp
user/wxLayout/wxlwindow.h

index e9b644ff091ffd1d4f3dd423c6c37b65d4cc9fa9..bf18ebeae026233ede700263b91e9992448d7528 100644 (file)
@@ -54,25 +54,16 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
    END_EVENT_TABLE()
 
 
-
-
-
-
 int orientation = wxPORTRAIT;
 
-
-
-
-
-   
-   MyFrame::MyFrame(void) :
+MyFrame::MyFrame(void) :
       wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) )
 {
    CreateStatusBar( 1 );
   
    SetStatusText( "wxLayout by Karsten Ballüder." );
 
-   wxMenu *file_menu = new wxMenu( "Menu 1" );
+   wxMenu *file_menu = new wxMenu;
    file_menu->Append( ID_CLEAR, "Clear");
    file_menu->Append( ID_ADD_SAMPLE, "Example");
    file_menu->Append( ID_EDIT, "Edit");
@@ -104,7 +95,7 @@ int orientation = wxPORTRAIT;
    SetMenuBar( menu_bar );
 
    m_lwin = new wxLayoutWindow(this);
-   m_lwin->SetEventId(ID_CLICK);
+   m_lwin->SetMouseTracking(true);
    m_lwin->GetLayoutList().SetEditable(true);
    m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false);
    m_lwin->SetFocus();
@@ -113,9 +104,11 @@ int orientation = wxPORTRAIT;
 void
 MyFrame::AddSampleText(wxLayoutList &llist)
 {
+   llist.SetFont(wxROMAN,16,wxNORMAL,wxNORMAL, false);
    llist.Insert("--");
    llist.LineBreak();
 
+   llist.SetFont(wxROMAN);
    llist.Insert("The quick brown fox jumps over the lazy dog.");
    llist.LineBreak();
    llist.Insert("Hello ");
@@ -203,7 +196,7 @@ MyFrame::Clear(void)
 void MyFrame::Edit(void)
 {
    wxLayoutList & llist = m_lwin->GetLayoutList();
-   m_lwin->SetEventId(ID_CLICK);
+   //m_lwin->SetEventId(ID_CLICK);
   
    llist.MoveCursor(0);
    llist.MoveCursor(5);
@@ -307,8 +300,10 @@ void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
 #endif
       wxPrinter printer;
       wxLayoutPrintout printout( m_lwin->GetLayoutList(),"My printout");
-      if (!printer.Print(this, &printout, TRUE))
-        wxMessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wxOK);
+      if (! printer.Print(this, &printout, TRUE))
+         wxMessageBox(
+            "There was a problem printing.\nPerhaps your current printer is not set correctly?",
+            "Printing", wxOK);  
 }
 
 void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
@@ -331,7 +326,9 @@ void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
       printData.SetOrientation(orientation);
 
       // Pass two printout objects: for preview, and possible printing.
-      wxPrintPreview *preview = new wxPrintPreview(new wxLayoutPrintout( m_lwin->GetLayoutList()), new wxLayoutPrintout( m_lwin->GetLayoutList()), & printData);
+      wxPrintPreview *preview = new wxPrintPreview(new
+                                                   wxLayoutPrintout(
+                                                      m_lwin->GetLayoutList()), new wxLayoutPrintout( m_lwin->GetLayoutList()), & printData);  
       if (!preview->Ok())
       {
         delete preview;
@@ -443,7 +440,7 @@ bool MyApp::OnInit(void)
 {
    wxFrame *frame = new MyFrame();
    frame->Show( TRUE );
-   wxSetAFMPath("/usr/local/src/wxWindows/misc/afm/");
+//   wxSetAFMPath("/usr/local/src/wxWindows/misc/afm/");
    return TRUE;
 };
 
index 551321b13cc9a92ff60e411191d5d3babea4bbf8..708a92153bd7db7b6d639fc197479df26542a6b4 100644 (file)
@@ -3,7 +3,7 @@
  *                                                                  *
  * (C) 1998 by Karsten Ballüder (Ballueder@usa.net)                 *
  *                                                                  *
- * $Id$       *
+ * $Id$
  *******************************************************************/
 
 /*
   - the cursor position is the position before an object, i.e. if the
     buffer starts with a text-object, cursor 0,0 is just before the
     first character
+
+  - the cursor position and size must be decided at layout/draw time
+    or the fonts will be wrong
+*/
+
+/*
+  Known wxGTK bugs:
+  - MaxX()/MaxY() don't get set
 */
 
 #ifdef __GNUG__
 #pragma implementation "wxllist.h"
 #endif
 
-// these two lines are for use in M:
 //#include "Mpch.h"
-//#include "gui/wxllist.h"
-
-#include   "wxllist.h"
+#ifdef M_BASEDIR
+#   include "gui/wxllist.h"
+#else
+#   include "wxllist.h"
+#endif
 
 #ifndef USE_PCH
-#  include   "iostream.h"
-
-#  include   <wx/dc.h>
-#  include   <wx/postscrp.h>
-#  include   <wx/print.h>
-#  include   <wx/log.h>
+#   include   "iostream.h"
+#   include   <wx/dc.h>
+#   include   <wx/postscrp.h>
+#   include   <wx/print.h>
+#   include   <wx/log.h>
 #endif
 
 #define   BASELINESTRETCH   12
@@ -46,7 +55,7 @@ static const char *g_aTypeStrings[] =
 };
    
 #  define   wxLayoutDebug        wxLogDebug
-#  define   WXL_VAR(x)           cerr << #x " = " << x ;
+#  define   WXL_VAR(x)           cerr << #x " = " << x << endl;
 #  define   WXL_DBG_POINT(p)     wxLogDebug(#p ": (%d, %d)", p.x, p.y)
 #  define   WXL_TRACE(f)         wxLogDebug(#f ": ")
 #  define   TypeString(t)        g_aTypeStrings[t]
@@ -76,6 +85,7 @@ wxLayoutObjectText::wxLayoutObjectText(const String &txt)
    m_Text = txt;
    m_Width = 0;
    m_Height = 0;
+   m_Position = wxPoint(-1,-1);
 }
 
 
@@ -87,22 +97,26 @@ wxLayoutObjectText::GetSize(CoordType *baseLine) const
 }
 
 void
-wxLayoutObjectText::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                         bool draw)
+wxLayoutObjectText::Draw(wxDC &dc)
+{
+   dc.DrawText(Str(m_Text), m_Position.x, m_Position.y);
+   m_IsDirty = false;
+}
+
+
+void
+wxLayoutObjectText::Layout(wxDC &dc, wxPoint position, CoordType baseLine)
 {
    long descent = 0l;
+
+   if(m_Position.x != position.x || m_Position.y != position.y)
+      m_IsDirty = true;
+   
+   m_Position = position;
    dc.GetTextExtent(Str(m_Text),&m_Width, &m_Height, &descent);
-   //FIXME: wxGTK does not set descent to a descent value yet.
-   if(descent == 0)
-      descent = (2*m_Height)/10;  // crude fix
    m_BaseLine = m_Height - descent;
-   position.y += baseLine-m_BaseLine;
-   if(draw)
-      dc.DrawText(Str(m_Text),position.x,position.y);
-   // Don't remove this, important help for debugging layout.
-#   ifdef   WXLAYOUT_DEBUG
-//   dc.DrawRectangle(position.x, position.y, m_Width, m_Height);
-#   endif
+   if(m_Position.x != position.x || m_Position.y != position.y)
+      m_IsDirty = true;
 }
 
 #ifdef WXLAYOUT_DEBUG
@@ -116,25 +130,35 @@ wxLayoutObjectText::Debug(void)
 
 //-------------------------- wxLayoutObjectIcon
 
+wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon const &icon)
+{
+   m_Position = wxPoint(-1,-1);
+   m_Icon = new wxIcon(icon);
+}
+
 wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon)
-   : m_Icon(icon)
 {
+   m_Icon = icon;
+}
+
+void
+wxLayoutObjectIcon::Draw(wxDC &dc)
+{
+   dc.DrawIcon(m_Icon,m_Position.x, m_Position.y);
 }
 
 void
-wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                         bool draw)
+wxLayoutObjectIcon::Layout(wxDC &dc, wxPoint position, CoordType baseLine)
 {
-   position.y += baseLine - m_Icon->GetHeight();
-   if(draw)
-      dc.DrawIcon(m_Icon,position.x,position.y);
+   if(m_Position.x != position.x || m_Position.y != position.y)
+      m_IsDirty = true;
+   m_Position = position;
 }
 
 wxPoint
 wxLayoutObjectIcon::GetSize(CoordType *baseLine) const
 {
-   wxASSERT(baseLine);
-   *baseLine = m_Icon->GetHeight();
+   if(baseLine)   *baseLine = m_Icon->GetHeight();
    return wxPoint(m_Icon->GetWidth(), m_Icon->GetHeight());
 }
 
@@ -179,20 +203,24 @@ wxLayoutObjectCmd::GetStyle(void) const
 }
 
 void
-wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint position, CoordType lineHeight,
-                        bool draw)
+wxLayoutObjectCmd::Draw(wxDC &dc)
 {
    wxASSERT(m_font);
-   // this get called even when draw==false, so that recalculation
-   // uses right font sizes
    dc.SetFont(m_font);
    if(m_ColourFG)
       dc.SetTextForeground(*m_ColourFG);
    if(m_ColourBG)
       dc.SetTextBackground(*m_ColourBG);
 }
+void
+wxLayoutObjectCmd::Layout(wxDC &dc, wxPoint p, CoordType baseline)
+{
+   m_Position = p; // required so we can find the right object for cursor
+   // this get called, so that recalculation uses right font sizes
+   Draw(dc);
+}
 
-//-------------------------- wxwxLayoutList
+//-------------------------- wxLayoutList
 
 wxLayoutList::wxLayoutList()
 {
@@ -262,217 +290,95 @@ wxLayoutList::GetSize(CoordType *max_x, CoordType *max_y,
    if(lineHeight) *lineHeight = m_LineHeight;
 }
 
-wxLayoutObjectBase *
-wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const
-                   &findCoords, int pageNo, bool reallyDraw)
+void
+wxLayoutList::ResetSettings(wxDC &dc)
 {
-   wxLayoutObjectList::iterator i;
+   // setting up the default:
+   dc.SetTextForeground( *wxBLACK );
+   dc.SetTextBackground( *wxWHITE );
+   dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background
+   dc.SetFont( *wxNORMAL_FONT );
+   if(m_DefaultSetting)
+      m_DefaultSetting->Draw(dc);
+}
+
+void
+wxLayoutList::Layout(wxDC &dc)
+{
+   iterator i;
 
-   // in case we need to look for an object
-   wxLayoutObjectBase *foundObject = NULL;
-   
    // first object in current line
    wxLayoutObjectList::iterator headOfLine;
-
-   // do we need to recalculate current line?
-   bool recalculate = false;
-
-   // do we calculate or draw? Either true or false.
-   bool draw = false;
-   // drawing parameters:
-   wxPoint position = wxPoint(0,0);
-   wxPoint position_HeadOfLine;
+   // where we draw next
+   wxPoint position, position_HeadOfLine;
+   // size of last object
+   wxPoint size;
    CoordType baseLine = m_FontPtSize;
    CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
-
-   // where to draw the cursor
-   wxPoint
-      cursorPosition = wxPoint(0,0),
-      cursorSize = wxPoint(1,baseLineSkip);
+   CoordType objBaseLine = baseLine;
+   wxLayoutObjectType type;
    
-   // the cursor position inside the object
-   CoordType cursorOffset = 0;
-   // object under cursor
-   wxLayoutObjectList::iterator cursorObject = FindCurrentObject(&cursorOffset);
+   // we need to count cursor positions
+   wxPoint cursorPos = wxPoint(0,0);
+   
+   wxLayoutObjectBase *cursorObject = NULL; // let's find it again
    
-   // queried from each object:
-   wxPoint       size = wxPoint(0,0);
-   CoordType     objBaseLine = baseLine;
-   wxLayoutObjectType type;
-
-   // used temporarily
-   wxLayoutObjectText *tobj = NULL;
-
-
-   // this is needed for printing to a printer:
-   // only interesting for printer/PS output
-   int pageWidth, pageHeight;   //GetSize() still needs int at the moment
    struct
    {
       int top, bottom, left, right;
    } margins;
 
-   int currentPage = 1;
+   margins.top = 0; margins.left = 0;
+   margins.right = -1;
+   margins.bottom = -1;
    
-   if(pageNo > 0)
-   {
-      dc.GetSize(&pageWidth, &pageHeight);
-      WXL_VAR(pageHeight);
-      margins.top = 0;   //(1*pageHeight)/10;    // 10%
-      margins.bottom = pageHeight;// (9*pageHeight)/10; // 90%
-      margins.left = 0;  //(1*pageWidth)/10;
-      margins.right = pageWidth; //(9*pageWidth)/10;
-   }
-   else
-   {
-      margins.top = 0; margins.left = 0;
-      margins.right = -1;
-      margins.bottom = -1;
-   }
    position.y = margins.top;
    position.x = margins.left;
-   
-   // if the cursorobject is a cmd, we need to find the first
-   // printable object:
-   while(cursorObject != end()
-         && (*cursorObject)->GetType() == WXLO_TYPE_CMD)
-      cursorObject++;
 
-   headOfLine = begin();
+   ResetSettings(dc);
+   
+   i = begin();
+   headOfLine = i;
    position_HeadOfLine = position;
 
-   // setting up the default:
-   dc.SetTextForeground( *wxBLACK );
-   dc.SetTextBackground( *wxWHITE );
-   dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background
-   dc.SetFont( *wxNORMAL_FONT );
-
-
-   //FIXME: who frees the brush, how long does it need to exist?
-   if(m_DefaultSetting)
-      m_DefaultSetting->Draw(dc,wxPoint(0,0),0,true);
-
-   // we calculate everything for drawing a line, then rewind to the
-   // begin of line and actually draw it
-   i = begin();
-   for(;;)
+   do
    {
-      recalculate = false;
-
       if(i == end())
-         break;
+         return;
+   
       type = (*i)->GetType();
-
-      // to initialise sizes of objects, we need to call Draw
-      if(draw && (pageNo == -1 || pageNo == currentPage))
-      {
-         (*i)->Draw(dc, position, baseLine, draw);
-#ifdef   WXLAYOUT_DEBUG
-         if(i == begin())
-            wxLogDebug("first position = (%d,%d)",(int) position.x, (int)position.y);
-#endif
-      }
-      // update coordinates for next object:
+      (*i)->Layout(dc, position, baseLine);
       size = (*i)->GetSize(&objBaseLine);
-      if(findObject && draw)  // we need to look for an object
-      {
-         if(findCoords.y >= position.y
-            && findCoords.y <= position.y+size.y
-            && findCoords.x >= position.x
-            && findCoords.x <= position.x+size.x)
-         {
-            foundObject = *i;
-            findObject = false; // speeds things up
-         }
-      }
-      // draw the cursor
-      if(m_Editable && draw && i == cursorObject)
-      {
-         WXL_VAR((**cursorObject).GetType());
-         WXL_VAR(m_CursorPosition.x); WXL_VAR(m_CursorPosition.y);
-         if(type == WXLO_TYPE_TEXT) // special treatment
-         {
-            long descent = 0l; long width, height;
-            tobj = (wxLayoutObjectText *)*i;
-            String  str = tobj->GetText();
-            WXL_VAR(m_CursorPosition.x);
-            str = str.substr(0, cursorOffset);
-            dc.GetTextExtent(Str(str), &width,&height, &descent);
-            cursorPosition = wxPoint(position.x+width,
-                                     position.y+(baseLineSkip-height));
-            cursorSize = wxPoint(1, height);
-         }
-         else if(type == WXLO_TYPE_LINEBREAK)
-         {
-            WXL_VAR(cursorOffset);
-            if(cursorOffset)
-               cursorPosition = wxPoint(0, position.y+baseLineSkip);
-            else
-               cursorPosition = wxPoint(0, position.y);
-            cursorSize = wxPoint(1,baseLineSkip);
-               
-         }
-         else
-         {
-            // this is not necessarily the most "beautiful" solution:
-            //cursorPosition = wxPoint(position.x, position.y);
-            //cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
-            cursorPosition = wxPoint(position.x+size.x, position.y+(size.y-baseLineSkip));
-            cursorSize = wxPoint(1, baseLineSkip);
-         }
-      }
-
       // calculate next object's position:
       position.x += size.x;
-      if(position.x > m_MaxX)
-         m_MaxX = position.x;
-      
+   
       // do we need to increase the line's height?
       if(size.y > baseLineSkip)
       {
          baseLineSkip = size.y;
-         recalculate = true;
+         i = headOfLine; position = position_HeadOfLine;
+         continue;
       }
       if(objBaseLine > baseLine)
       {
          baseLine = objBaseLine;
-         recalculate = true;
+         i = headOfLine; position = position_HeadOfLine;
+         continue;
       }
 
-      // now check whether we have finished handling this line:
-      if(type == WXLO_TYPE_LINEBREAK || i == tail())
+      // when we reach here, the coordinates are valid, this part of
+      // the loop gets run only once per object
+      if(position.x > m_MaxX)
+         m_MaxX = position.x;
+      if(type == WXLO_TYPE_LINEBREAK)
       {
-         if(recalculate)  // do this line again
-         {
-            position.x = position_HeadOfLine.x;
-            i = headOfLine;
-            continue;
-         }
-
-         if(! draw) // finished calculating sizes
-         {
-            // if the this line needs to go onto a new page, we need
-            // to change pages before drawing it:
-            if(pageNo > 0 && position.y > margins.bottom)
-            {
-               currentPage++;
-               position_HeadOfLine.y = margins.top;
-            }
-            if(reallyDraw && (pageNo == -1 || pageNo == currentPage))
-            {
-               // do this line again, this time drawing it
-               position = position_HeadOfLine;
-               draw = true;
-               i = headOfLine;
-               continue;
-            }
-         }
-         else // we have drawn a line, so continue calculating next one
-            draw = false;
+         cursorPos.x = 0; cursorPos.y ++;
       }
-
-      // is it a linebreak?
-      if(type == WXLO_TYPE_LINEBREAK || i == tail())
+      else
+         cursorPos.x += (**i).CountPositions();
+      
+      // now check whether we have finished handling this line:
+      if(type == WXLO_TYPE_LINEBREAK && i != tail()) 
       {
          position.x = margins.left;
          position.y += baseLineSkip;
@@ -483,18 +389,150 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const
          headOfLine++;
          position_HeadOfLine = position;
       }
+      if(cursorObject == NULL && cursorPos.y == m_CursorPosition.y) // look for cursor
+      {
+         if(cursorPos.x >= m_CursorPosition.x &&
+            m_CursorPosition.x-cursorPos.x+(**i).CountPositions()) // cursor is in current object
+         {
+            cursorObject = *i;
+            CalculateCursor(dc);
+         }
+      }
+      i++;
+   }
+   while(i != end());
+   m_MaxY = position.y + baseLineSkip;
+}
+
+void
+wxLayoutList::Draw(wxDC &dc,
+                   CoordType fromLine, CoordType toLine,
+                   iterator start)
+{
+   Layout(dc); // FIXME just for now
+
+   ResetSettings(dc);
+
+   wxLayoutObjectList::iterator i;
+   if(start == iterator(NULL))
+      start = begin();
+
+   while( i != end() && (**i).GetPosition().y < fromLine)
       i++;
+   for( i = start ;
+        i != end() && (toLine == -1 || (**i).GetPosition().y < toLine) ;
+        i++ )
+      (*i)->Draw(dc);
+}
+
+/** Erase at least to end of line */
+void
+wxLayoutList::EraseAndDraw(wxDC &dc, iterator start)
+{
+   //look for begin of line
+   while(start != end() && start != begin() && (**start).GetType() !=
+         WXLO_TYPE_LINEBREAK)
+      start--;
+   if(start == iterator(NULL))
+      start = begin();
+   if(start == iterator(NULL))
+      return;
+   
+   wxPoint p = (**start).GetPosition();
+
+   WXL_VAR(p.x);WXL_VAR(p.y);
+   //FIXME: wxGTK: MaxX()/MaxY() broken
+   //WXL_VAR(dc.MaxX()); WXL_VAR(dc.MaxY());
+   dc.SetBrush(*wxWHITE_BRUSH);
+   dc.SetPen(wxPen(*wxWHITE,0,wxTRANSPARENT));
+   dc.DrawRectangle(p.x,p.y,2000,2000); //dc.MaxX(),dc.MaxY());
+   Draw(dc,-1,-1,start);
+   //dc.DrawRectangle(p.x,p.y,2000,2000); //dc.MaxX(),dc.MaxY());
+}
+
+
+void
+wxLayoutList::CalculateCursor(wxDC &dc)
+{
+   CoordType width, height, descent;
+   CoordType baseLineSkip = 20; //FIXME
+
+   CoordType offset;
+   wxLayoutObjectBase &obj = **FindCurrentObject(&offset);
+
+   WXL_VAR(offset);
+   DrawCursor(dc,true); // erase it
+   m_CursorCoords = obj.GetPosition();
+   WXL_VAR(m_CursorCoords.x); 
+   if(obj.GetType() == WXLO_TYPE_TEXT)
+   {
+      wxLayoutObjectText *tobj = (wxLayoutObjectText *)&obj;
+      String & str = tobj->GetText();
+      String sstr = str.substr(0,offset);
+      WXL_VAR(sstr);
+      dc.GetTextExtent(sstr,&width,&height,&descent);
+      WXL_VAR(width);
+      m_CursorCoords = wxPoint(m_CursorCoords.x+width,
+                               m_CursorCoords.y);
+      m_CursorSize = wxPoint(2,height);
    }
-   // draw the cursor
-   if(m_Editable)
+   else if(obj.GetType() == WXLO_TYPE_LINEBREAK)
    {
-      dc.DrawRectangle(cursorPosition.x, cursorPosition.y,
-                       cursorSize.x, cursorSize.y);
+      m_CursorCoords = wxPoint(0, m_CursorCoords.y);
+      m_CursorSize = wxPoint(2,baseLineSkip);
+   }
+   else
+   {
+      // this is not necessarily the most "beautiful" solution:
+      //cursorPosition = wxPoint(position.x, position.y);
+      //cursorSize = wxPoint(size.x > 0 ? size.x : 1,size.y > 0 ? size.y : baseLineSkip);
+      m_CursorCoords = wxPoint(m_CursorCoords.x+obj.GetSize().x, m_CursorCoords.y);
+      m_CursorSize = wxPoint(2, obj.GetSize().y);
+      if(m_CursorSize.y < 1) m_CursorSize.y = baseLineSkip;
+   }
+   WXL_VAR(m_CursorCoords.x); 
+   m_CursorMoved = false; // coords are valid
+}
+
+void
+wxLayoutList::DrawCursor(wxDC &dc, bool erase)
+{
+
+   if(erase)
+   {
+      //dc.SetBrush(*wxWHITE_BRUSH);
+      //dc.SetPen(wxPen(*wxWHITE,1,wxSOLID));
+      //dc.DrawRectangle(m_CursorCoords.x, m_CursorCoords.y, m_CursorSize.x, m_CursorSize.y);
+      dc.Blit(m_CursorCoords.x, m_CursorCoords.y, m_CursorSize.x,
+              m_CursorSize.y, &m_CursorMemDC,
+              0, 0, 0, 0);
+   }
+   else
+   {
+      if(IsDirty() || CursorMoved())
+      {
+         DrawCursor(dc,true);
+         Layout(dc);
+      }
+      // Save background:
+      wxBitmap bm(m_CursorSize.x,m_CursorSize.y);
+      m_CursorMemDC.SelectObject(bm);
+      m_CursorMemDC.Blit(0, 0, m_CursorSize.x, m_CursorSize.y,
+                         &dc, m_CursorCoords.x,
+                         m_CursorCoords.y, 0, 0);
+      dc.SetBrush(*wxBLACK_BRUSH);
+      dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
+      dc.DrawRectangle(m_CursorCoords.x, m_CursorCoords.y,
+                       m_CursorSize.x, m_CursorSize.y);
    }
-   m_MaxY = position.y;
-   return foundObject;
 }
 
+
+
+
+
+
+
 #ifdef WXLAYOUT_DEBUG
 void
 wxLayoutList::Debug(void)
@@ -571,13 +609,27 @@ wxLayoutObjectList::iterator
 wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
 {
    wxPoint object = wxPoint(0,0);  // runs along the objects
-   CoordType width;
-   wxLayoutObjectList::iterator i;
-
-#ifdef WXLAYOUT_DEBUG
-   wxLayoutDebug("Looking for object at (%d, %d)", cpos->x, cpos->y);
-#endif
-   for(i = begin(); i != end() && object.y <= cpos->y; i++)
+   CoordType width = 0;
+   wxLayoutObjectList::iterator i, begin_it;
+   int go_up;
+   
+//#ifdef WXLAYOUT_DEBUG
+//   wxLayoutDebug("Looking for object at (%d, %d)", cpos->x, cpos->y);
+//#endif
+
+   // optimisation: compare to last looked at object:
+   if(cpos->y > m_FoundCursor.y || (cpos->y == m_FoundCursor.y &&
+                                    cpos->x >= m_FoundCursor.x))
+      go_up = 1;
+   else
+      go_up = 0;
+
+   //broken at the moment
+   //begin_it = m_FoundIterator;
+   //m_FoundCursor = *cpos;
+   begin_it = begin();
+   go_up = 1;
+   for(i = begin_it; i != end() && object.y <= cpos->y; )
    {
       width = (**i).CountPositions();
       if(cpos->y == object.y) // a possible candidate
@@ -587,48 +639,52 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
             if(cpos->x == object.x)
             {
                if(offset) *offset = 0;
-               return i;
+               return m_FoundIterator = i;
             }
             if(offset) *offset=1;
             cpos->x = object.x;
-            return i;
+            return m_FoundIterator = i;
          }
          if(cpos->x >= object.x && cpos->x <= object.x+width) // overlap
          {
             if(offset) *offset = cpos->x-object.x;
-#ifdef WXLAYOUT_DEBUG
-            wxLayoutDebug("   found object at (%d, %d), type: %s",
-                          object.x,  object.y, TypeString((*i)->GetType()));
-#endif      
-            return i;
+//#ifdef WXLAYOUT_DEBUG
+//            wxLayoutDebug("   found object at (%d, %d), type: %s",
+//                          object.x,  object.y, TypeString((*i)->GetType()));
+//#endif      
+            return m_FoundIterator = i;
          }
       }
-// no overlap, increment coordinates
+      // no overlap, increment coordinates
       object.x += width;
       if((**i).GetType() == WXLO_TYPE_LINEBREAK)
       {
          object.x = 0;
          object.y++;
       }
-   }
-#ifdef WXLAYOUT_DEBUG
-   wxLayoutDebug("   not found");
-#endif
+      if(go_up)
+         i++;
+      else
+         i--;
+   }//for
+//#ifdef WXLAYOUT_DEBUG
+//   wxLayoutDebug("   not found");
+//#endif
 // return last object, coordinates of that one:
    i = tail();
    if(i == end())
-      return i;
+      return m_FoundIterator = i;
    if((**i).GetType()==WXLO_TYPE_LINEBREAK)
    {
       if(offset)
          *offset = 1;
-      return i;
+      return m_FoundIterator = i;
    }
    cpos->x = object.x; // would be the coordinate of next object
    cpos->y = object.y;
    cpos->x += width; // last object's width
    if(*offset)  *offset = cpos->x-object.x;
-   return i; // not found
+   return m_FoundIterator = i; // not found
 }
 
 wxLayoutObjectList::iterator 
@@ -652,6 +708,8 @@ wxLayoutList::MoveCursor(int dx, int dy)
    CoordType offs, lineLength;
    wxLayoutObjectList::iterator i;
 
+   m_CursorMoved = true;  
+   
    bool rc = true; // have we moved?
 
    if(dy > 0 && m_CursorPosition.y < m_MaxLine)
@@ -744,6 +802,8 @@ wxLayoutList::Delete(CoordType count)
 
    WXL_VAR(count);
 
+   m_bModified = true;
+   
    CoordType offs;
    wxLayoutObjectList::iterator i;
       
@@ -822,11 +882,14 @@ wxLayoutList::Delete(CoordType count)
 void
 wxLayoutList::Insert(wxLayoutObjectBase *obj)
 {
-   wxASSERT(obj);
+   wxCHECK_RET( obj, "no object to insert" );
+
+   m_bModified = true;
+
    CoordType offs;
    wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
 
-   WXL_TRACE(Insert(obj));
+//   WXL_TRACE(Insert(obj));
 
    if(i == end())
       push_back(obj);
@@ -861,6 +924,7 @@ wxLayoutList::Insert(wxLayoutObjectBase *obj)
    m_CursorPosition.x += obj->CountPositions();
    if(obj->GetType() == WXLO_TYPE_LINEBREAK)
       m_MaxLine++;
+   m_CursorMoved = true;
 }
 
 void
@@ -869,11 +933,13 @@ wxLayoutList::Insert(String const &text)
    wxLayoutObjectText *tobj = NULL;
    wxLayoutObjectList::iterator j;
 
-   WXL_TRACE(Insert(text));
+//   WXL_TRACE(Insert(text));
 
    if(! m_Editable)
       return;
 
+   m_bModified = true;
+
    CoordType offs;
    wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
 
@@ -923,24 +989,9 @@ wxLayoutList::Insert(String const &text)
          }
       }
       break;
-#if 0
-   default:
-      j = i; j--;
-      WXL_TRACE(checking previous object);
-      if(j != end() && (**j).GetType() == WXLO_TYPE_TEXT)
-      {
-         tobj = (wxLayoutObjectText *)*j;
-         tobj->GetText()+=text;
-      }
-      else  // insert a new text object
-      {
-         WXL_TRACE(creating new object);
-         Insert(new wxLayoutObjectText(text));  //FIXME not too optimal, slow
-         return;  // position gets incremented in Insert(obj)
-      }
-#endif
    }
    m_CursorPosition.x += strlen(text.c_str());
+   m_CursorMoved = true;
 }
 
 CoordType
@@ -972,12 +1023,18 @@ void
 wxLayoutList::Clear(int family, int size, int style, int weight,
                     int underline, char const *fg, char const *bg)
 {
+   m_bModified = true;
+   m_CursorMoved = true;
+   m_dirty = true;  // force redraw/recalc
    wxLayoutObjectList::iterator i = begin();
 
+   wxBitmap bm(1,1);
+   m_CursorMemDC.SelectObject(bm);
+
    while(i != end()) // == while valid
       erase(i);
 
-// set defaults
+   // set defaults
    m_FontPtSize = size;
    m_FontUnderline = false;
    m_FontFamily = family;
@@ -995,9 +1052,13 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
    m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10;
    m_MaxX = 0; m_MaxY = 0;
 
+
+   m_FoundCursor = wxPoint(0,0);
+   m_FoundIterator = begin();
    
    if(m_DefaultSetting)
       delete m_DefaultSetting;
+
    m_DefaultSetting = new
       wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
                         m_FontWeight,m_FontUnderline,
@@ -1005,72 +1066,94 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
 }
 
 
+wxLayoutObjectBase *
+wxLayoutList::Find(wxPoint coords) const
+{
+   wxLayoutObjectList::iterator i = begin();
+
+   wxPoint topleft, bottomright;
+   
+   while(i != end()) // == while valid
+   {
+      wxLayoutObjectBase *object = *i;
+      topleft = object->GetPosition();
+      if(coords.y >= topleft.y && coords.x >= topleft.x)
+      {
+         bottomright = topleft;
+         bottomright.x += object->GetSize().x;
+         bottomright.y += object->GetSize().y;
+         if(coords.x <= bottomright.x && coords.y <= bottomright.y)
+            return *i;
+      }
+      i++;
+   }
+   return NULL;
+}
+
 
 /******************** printing stuff ********************/
 
 bool wxLayoutPrintout::OnPrintPage(int page)
 {
-  wxDC *dc = GetDC();
-  if (dc)
-  {
-     m_llist->Draw(*dc,false,wxPoint(0,0),page);
-     return TRUE;
-  }
-  else
-    return FALSE;
+   wxDC *dc = GetDC();
+   int top, bottom,width,height;
+   if (dc)
+   {
+      dc->GetSize(&width, &height);
+      
+      top = (page - 1) * (9*height)/10;
+      bottom = top + (9*height)/10;
+
+      if( top >= m_llist->GetSize().y)
+         return false;
+      m_llist->Draw(*dc,top,bottom);
+      return true;
+   }
+   else
+      return false;
 }
 
 bool wxLayoutPrintout::OnBeginDocument(int startPage, int endPage)
 {
   if (!wxPrintout::OnBeginDocument(startPage, endPage))
-    return FALSE;
+    return false;
 
-  return TRUE;
+  return true;
 }
 
-void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+void
+wxLayoutPrintout::OnPreparePrinting(void)
 {
+   
+}
+
 
+void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+   // ugly hack to get number of pages
+   wxPostScriptDC psdc("tmp.ps",false);
+   int width,height;
+   psdc.GetSize(&width, &height); // that's all we need it for
+      
+   
    // This code doesn't work, because we don't have a DC yet.
    // How on earth are we supposed to calculate the number of pages then?
-   *minPage = 0;    // set this to 0 to disable editing of page numbers 
-   *maxPage = 100;
-
-   *selPageFrom = 0; // set this to 0 to hide page number controls
-   *selPageTo = 100;  
-
-//   *minPage = 1;
-//   *maxPage = 32000;
-
-//   *selPageFrom = 1;
-//   *selPageTo = 1;
 
-#if 0
-   CoordType height;
-   int pageWidth, pageHeight;
-
-   wxDC *dc = GetDC();
-   wxASSERT(dc);
-
-   dc->GetSize(&pageWidth, &pageHeight);
-// don't draw but just recalculate sizes:
-   m_llist->Draw(*dc,false,wxPoint(0,0),-1,false);
-   m_llist->GetSize(NULL,&height,NULL);
-   
-   *minPage = 1;
-   *maxPage = height/pageHeight+1;
+   *minPage = 0;
+   *maxPage = (int)( m_llist->GetSize().y / (float)(0.9*height) + 0.5);
 
    *selPageFrom = 1;
    *selPageTo = *maxPage;
+
    m_maxPage = *maxPage;
-#endif
    
 }
 
 bool wxLayoutPrintout::HasPage(int pageNum)
 {
-   return pageNum <= 5; // for testing
-//   return m_maxPage >= pageNum;
+   if(m_maxPage != -1)
+      return pageNum <= m_maxPage;
+   return true;
 }
 
 
index 4916b960b4ed40aadf87554c450580460fd909ee..512b9117df45e58a09cad99cd8c17468cc0f30ff 100644 (file)
 #include   "kbList.h"
 
 #include   "wx/wx.h"
-#include "wx/print.h"
-#include "wx/printdlg.h"
-#include "wx/generic/printps.h"
-#include "wx/generic/prntdlgg.h"
+#include   "wx/print.h"
+#include   "wx/printdlg.h"
+#include   "wx/generic/printps.h"
+#include   "wx/generic/prntdlgg.h"
 
 // skip the following defines if embedded in M application
 #ifdef   M_BASEDIR
@@ -30,6 +30,9 @@
 #   define WXLAYOUT_DEBUG
     // The wxLayout classes can be compiled with std::string instead of wxString
     //#   define USE_STD_STRING
+#   define WXMENU_LAYOUT_LCLICK     1111
+#   define WXMENU_LAYOUT_RCLICK    1112
+#   define WXMENU_LAYOUT_DBLCLICK   1113
 #endif
 
 #ifdef USE_STD_STRING
@@ -62,46 +65,68 @@ class wxFont;
 class wxLayoutObjectBase
 {
 public:
+   struct UserData
+   {
+      virtual ~UserData() { }
+   };
+
    /// return the type of this object
    virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_INVALID; } ;
-   /** Draws an object.
+   /** Calculates the position etc of an object.
        @param dc the wxDC to draw on
        @param position where to draw the top left corner
        @param baseLine the baseline for alignment, from top of box
-       @draw if set to false, do not draw but just calculate sizes
    */
-   virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                     bool draw = true) {};
+   virtual void Layout(wxDC & dc,
+                       wxPoint position,
+                       CoordType baseLine) {}
+
+   /** Draws an object.
+       @param dc the wxDC to draw on
+   */
+   virtual void Draw(wxDC & dc) {}
 
-   /** Calculates and returns the size of the object. May need to be
-       called twice to work.
+   /** Calculates and returns the size of the object. 
        @param baseLine pointer where to store the baseline position of 
        this object (i.e. the height from the top of the box to the
        baseline)
        @return the size of the object's box in pixels
    */
-   virtual wxPoint GetSize(CoordType *baseLine) const { return
-                                                           wxPoint(0,0); };
+   virtual wxPoint GetSize(CoordType * baseLine = NULL) const
+      { return wxPoint(0,0); }
+
+   /** Calculates and returns the position of the object.
+       @return the size of the object's box in pixels
+   */
+   virtual wxPoint GetPosition(void) const { return m_Position; }
+
    /// returns the number of cursor positions occupied by this object
    virtual CoordType CountPositions(void) const { return 1; }
 
    /// constructor
    wxLayoutObjectBase() { m_UserData = NULL; }
-   /// note: any user data will be freed at the time the object is deleted
-   virtual ~wxLayoutObjectBase() { if(m_UserData) delete m_UserData; }
+   /// delete the user data
+   virtual ~wxLayoutObjectBase() { delete m_UserData; }
+
 #ifdef WXLAYOUT_DEBUG
    virtual void Debug(void);
 #endif
 
+   /// query whether coordinates have changed since last drawing
+   virtual bool IsDirty(void) const { return true; }  
+   
    /** Tells the object about some user data. This data is associated
        with the object and will be deleted at destruction time.
    */
-   void   SetUserData(void *data) { m_UserData = data; }
+   void   SetUserData(UserData *data) { m_UserData = data; }
    /** Return the user data. */
    void * GetUserData(void) const { return m_UserData; }
+   
 private:
    /// optional data for application's use
-   void * m_UserData;
+   UserData *m_UserData;
+protected:
+   wxPoint m_Position;
 };
 
 /// Define a list type of wxLayoutObjectBase pointers.
@@ -112,44 +137,58 @@ KBLIST_DEFINE(wxLayoutObjectList, wxLayoutObjectBase);
 class wxLayoutObjectText : public wxLayoutObjectBase
 {
 public:
+   wxLayoutObjectText(const String &txt);
+
    virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; }
-   virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                     bool draw = true);
+   virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine);
+   virtual void Draw(wxDC &dc);
    /** This returns the height and in baseLine the position of the
        text's baseline within it's box. This is needed to properly
        align text objects.
    */
-   virtual wxPoint GetSize(CoordType *baseLine) const;
+   virtual wxPoint GetSize(CoordType *baseLine = NULL) const;
+
 #ifdef WXLAYOUT_DEBUG
    virtual void Debug(void);
 #endif
 
-   wxLayoutObjectText(const String &txt);
    virtual CoordType CountPositions(void) const { return strlen(m_Text.c_str()); }
+   virtual bool IsDirty(void) const { return m_IsDirty; }  
 
    // for editing:
    String & GetText(void) { return m_Text; }
    void SetText(String const &text) { m_Text = text; }
+
 private:
    String m_Text;
    /// size of the box containing text
    long   m_Width, m_Height;
    /// the position of the baseline counted from the top of the box
    long   m_BaseLine;
+   /// coordinates have changed
+   bool m_IsDirty;
 };
 
 /// icon/pictures:
 class wxLayoutObjectIcon : public wxLayoutObjectBase
 {
 public:
-   virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; }
-   virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                     bool draw = true);
-   virtual wxPoint GetSize(CoordType *baseLine) const;
    wxLayoutObjectIcon(wxIcon *icon);
+   wxLayoutObjectIcon(wxIcon const &icon);
+
+   ~wxLayoutObjectIcon() { delete m_Icon; }
+
+   virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; }
+   virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine);
+   virtual void Draw(wxDC &dc);
+
+   virtual wxPoint GetSize(CoordType *baseLine = NULL) const;
+   virtual bool IsDirty(void) const { return m_IsDirty; }  
 
 private:
    wxIcon *m_Icon;
+   /// coordinates have changed
+   bool m_IsDirty;
 };
 
 /// for export to html:
@@ -166,8 +205,8 @@ class wxLayoutObjectCmd : public wxLayoutObjectBase
 {
 public:
    virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; }
-   virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine,
-                     bool draw = true);
+   virtual void Draw(wxDC &dc);
+   virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine);
    wxLayoutObjectCmd(int size, int family, int style, int weight,
                 bool underline,
                 wxColour const *fg, wxColour const *bg);
@@ -212,44 +251,76 @@ public:
 
    /// adds an object:
    void AddObject(wxLayoutObjectBase *obj);
+   /// adds a text object
    void AddText(String const &txt);
-
+   /// adds a line break
    void LineBreak(void);
+   /// sets font parameters
    void SetFont(int family, int size, int style,
                 int weight, int underline,
                 wxColour const *fg,
                 wxColour const *bg);
+   /// sets font parameters, colours by name
    void SetFont(int family=-1, int size = -1, int style=-1,
                 int weight=-1, int underline = -1,
-                char const *fg = (const char *) NULL,
-                char const *bg = (const char *) NULL);
+                char const *fg = NULL,
+                char const *bg = NULL);
+   /// set font family
    inline void SetFontFamily(int family) { SetFont(family); }
+   /// set font size
    inline void SetFontSize(int size) { SetFont(-1,size); }
+   /// set font style
    inline void SetFontStyle(int style) { SetFont(-1,-1,style); }
+   /// set font weight
    inline void SetFontWeight(int weight) { SetFont(-1,-1,-1,weight); }
+   /// toggle underline flag
    inline void SetFontUnderline(bool ul) { SetFont(-1,-1,-1,-1,(int)ul); }
-   inline void SetFontColour(char const *fg, char const *bg = (const char *) NULL) { SetFont(-1,-1,-1,-1,-1,fg,bg); }
+   /// set font colours by name
+   inline void SetFontColour(char const *fg, char const *bg = NULL) { SetFont(-1,-1,-1,-1,-1,fg,bg); }
       
    
-   /** Draw the list on a given DC.
+   /** Re-layouts the list on a DC.
        @param findObject if true, return the object occupying the
        position specified by coords
        @param coords position where to find the object
-       @pageNo if > 0, print only that page of a document (for
+       @param pageNo if > 0, print only that page of a document (for
        printing)
-       @reallyDraw set this to false if you don't want to draw but just calculate the coordinates
+       @param reallyDraw set this to false if you don't want to draw but
+       just calculate the coordinates
+       @param hasDrawn set to true if a page has been printed
        @return if findObject == true, the object or NULL
    */
-   wxLayoutObjectBase *Draw(wxDC &dc, bool findObject = false,
-                            wxPoint const &coords = wxPoint(0,0),
-                            int pageNo = -1, bool reallyDraw = true);
+   void Layout(wxDC &dc);
+                            
+  /** Draw the list on a given DC.
+      @param pageNo if > 0, print only that page of a document (for
+      printing)
+   */
+   void Draw(wxDC &dc,
+             CoordType fromLine = -1,
+             CoordType toLine = -1,
+             iterator start = iterator(NULL));
 
+   /** Deletes at least to the end of line and redraws */
+   void EraseAndDraw(wxDC &dc, iterator start = iterator(NULL));
+   
+   /** Finds the object occupying a certain screen position.
+       @return pointer to wxLayoutObjectBase or NULL if not found
+   */
+   wxLayoutObjectBase *Find(wxPoint coords) const;
+   
 #ifdef WXLAYOUT_DEBUG
    void Debug(void);
    void ShowCurrentObject();
 #endif
 
-   
+   /// dirty?
+   bool IsDirty() const { return m_bModified; }
+   bool CursorMoved(void) const { return m_CursorMoved; }  
+
+   /// called after the contents is saved, for example
+   void ResetDirty() { m_bModified = FALSE; }
+
    /// for access by wxLayoutWindow:
    void GetSize(CoordType *max_x, CoordType *max_y,
                 CoordType *lineHeight);
@@ -264,7 +335,13 @@ public:
    /// move cursor, returns true if it could move to the desired position
    bool MoveCursor(int dx = 0, int dy = 0);
    void SetCursor(wxPoint const &p) { m_CursorPosition = p; }
+   void DrawCursor(wxDC &dc, bool erase = false);
+   
+   /// Get current cursor position cursor coords
    wxPoint GetCursor(void) const { return m_CursorPosition; }
+   /// Gets graphical coordinates of cursor
+   wxPoint GetCursorCoords(void) const { return m_CursorCoords; }
+   
    /// delete one or more cursor positions
    void Delete(CoordType count = 1);
    void Insert(String const &text);
@@ -275,13 +352,15 @@ public:
    /// return a pointer to the default settings:
    wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; }
 
-   wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = (CoordType *) NULL);
+   wxLayoutObjectList::iterator FindCurrentObject(CoordType *offset = NULL);
    // get the length of the line with the object pointed to by i, offs 
    // only used to decide whether we are before or after linebreak
    CoordType GetLineLength(wxLayoutObjectList::iterator i,
                            CoordType offs = 0);
    wxLayoutPrintout *MakePrintout(wxString const &name);
 
+   /// Return maximum X,Y coordinates
+   wxPoint GetSize(void) const { return wxPoint(m_MaxX, m_MaxY); }
 //@}
 protected:
    /// font parameters:
@@ -296,6 +375,11 @@ protected:
    
    /// needs recalculation?
    bool m_dirty;
+   /// cursor moved
+   bool m_CursorMoved;
+
+   /// needs saving (i.e., was modified?)
+   bool m_bModified;
 
    // the currently updated line:
    /// where do we draw next:
@@ -308,28 +392,46 @@ protected:
    CoordType m_MaxY;
 
    //---- this is needed for editing:
-   /// where is the text cursor:
+   /// where is the text cursor (column,line):
    wxPoint   m_CursorPosition;
+   /// where to draw the cursor
+   wxPoint   m_CursorCoords;
+   /// how large to draw it
+   wxPoint   m_CursorSize;
+
+   /// to store content overwritten by cursor
+   wxMemoryDC m_CursorMemDC;
+
    /// which is the last line
    CoordType m_MaxLine;
    /// can we edit it?
    bool      m_Editable;
    /// find the object to the cursor position and returns the offset
    /// in there
-   wxLayoutObjectList::iterator FindObjectCursor(wxPoint *cpos, CoordType *offset = (CoordType *) NULL);
-   
+   wxLayoutObjectList::iterator FindObjectCursor(wxPoint *cpos, CoordType *offset = NULL);
+private:
+   /// Resets the font settings etc to default values
+   void ResetSettings(wxDC &dc);
+   /// calculates current cursor coordinates, called in Layout()
+   void CalculateCursor(wxDC &dc);
+   /// remembers the last cursor position for which FindObjectCursor was called
+   wxPoint m_FoundCursor;
+   /// remembers the iterator to the object related to m_FoundCursor
+   wxLayoutObjectList::iterator m_FoundIterator;
 };
 
 class wxLayoutPrintout: public wxPrintout
 {
  public:
-   wxLayoutPrintout(wxLayoutList &llist, wxString const & title = "My printout"):wxPrintout(title)
+   wxLayoutPrintout(wxLayoutList &llist, wxString const & title = "My printout")
+      :wxPrintout(title)
       { m_llist = &llist; m_maxPage = 0; }
-  bool OnPrintPage(int page);
-  bool HasPage(int page);
-  bool OnBeginDocument(int startPage, int endPage);
+   bool OnPrintPage(int page);
+   bool HasPage(int page);
+   bool OnBeginDocument(int startPage, int endPage);
    void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int
                     *selPageTo);
+   void OnPreparePrinting(void);
 private:
    wxLayoutList *m_llist;
    int           m_maxPage;
index 2e3f9f54c4fd1ed3d751d238722dc4a5bc1b211f..17900885177c2fffd370d57f27cb784af49ba70c 100644 (file)
 #   pragma implementation "wxlparser.h"
 #endif
 
-#include   "wxllist.h"
-#include   "wxlparser.h"
+//#include "Mpch.h"
+#ifdef M_BASEDIR
+#   include "gui/wxllist.h"
+#   include "gui/wxlparser.h"
+#else
+#   include "wxllist.h"
+#   include "wxlparser.h"
+#endif
 
 #define   BASE_SIZE 12
 
+inline static bool IsEndOfLine(const char *p)
+{
+   // in addition to Unix EOL convention we also (but not instead) understand
+   // the DOS one under Windows
+   return
+#ifdef OS_WIN
+      ((*p == '\r') && (*(p + 1) == '\n')) ||
+#endif
+      (*p == '\n');
+}
+
 void wxLayoutImportText(wxLayoutList &list, String const &str)
 {
    char * cptr = (char *)str.c_str(); // string gets changed only temporarily
@@ -23,15 +40,22 @@ void wxLayoutImportText(wxLayoutList &list, String const &str)
    
    for(;;)
    {
-      begin = cptr++;
-      while(*cptr && *cptr != '\n')
+      begin = cptr;
+      while( *cptr && !IsEndOfLine(cptr) )
          cptr++;
       backup = *cptr;
       *cptr = '\0';
       list.Insert(begin);
       *cptr = backup;
-      if(backup == '\n')
+
+      // check if it's the end of this line
+      if ( IsEndOfLine(cptr) )
+      {
+         // if it was "\r\n", skip the following '\n'
+         if ( *cptr == '\r' )
+            cptr++;
          list.LineBreak();
+      }
       else if(backup == '\0') // reached end of string
          break;
       cptr++;
@@ -168,8 +192,9 @@ String wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
          *str += '\n';
          break;
       case WXLO_TYPE_CMD:
-         //wxASSERT(mode == WXLO_EXPORT_AS_HTML,"reached cmd object in text mode")
-         assert(mode == WXLO_EXPORT_AS_HTML);
+         wxASSERT_MSG( mode == WXLO_EXPORT_AS_HTML,
+                       "reached cmd object in text mode" );
+         
          *str += wxLayoutExportCmdAsHTML(*(wxLayoutObjectCmd const
                                            *)*from, &s_si);
          break;
index 57af29d32c5e222c4f6b759fa012445241ac6ef1..f7f158e334f99545d1d8bdf4f73a33271a6f3a15 100644 (file)
 #   pragma implementation "wxlwindow.h"
 #endif
 
-#include   "wxlwindow.h"
+//#include "Mpch.h"
 
-#define   VAR(x)   cout << #x"=" << x << endl;
+#ifdef M_BASEDIR
+#   ifndef USE_PCH
+#     include "Mcommon.h"
+#     include "gui/wxMenuDefs.h"
+#   endif // USE_PCH
+#   include "gui/wxlwindow.h"
+#else
+#   include "wxlwindow.h"
+#   define TRACEMESSAGE(x)
+#endif
+#  define   WXL_VAR(x)           cerr << #x " = " << x ;
 
 BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
    EVT_PAINT    (wxLayoutWindow::OnPaint)
    EVT_CHAR     (wxLayoutWindow::OnChar)
-   EVT_LEFT_DOWN(wxLayoutWindow::OnMouse)
+
+   EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick)
+   EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick)
+   EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick)
 END_EVENT_TABLE()
 
 wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
@@ -26,7 +39,15 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
 
 {
    m_ScrollbarsSet = false;
-   m_EventId = -1;
+   m_doSendEvents = false;
+   m_ViewStartX = 0; m_ViewStartY = 0;
+
+
+   CoordType
+      max_x, max_y, lineHeight;
+   m_llist.GetSize(&max_x, &max_y, &lineHeight);
+   SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1);
+   EnableScrolling(true,true);
 }
 
 #ifdef __WXMSW__
@@ -38,34 +59,45 @@ wxLayoutWindow::MSWGetDlgCode()
 }
 #endif //MSW
 
+void
+wxLayoutWindow::Update(void)
+{
+   wxClientDC  dc(this);
+   PrepareDC(dc);
+   if(IsDirty())
+   {
+      DoPaint(dc);
+      UpdateScrollbars();
+      ResetDirty();
+   }
+   m_llist.DrawCursor(dc);
+}
 
 void
-wxLayoutWindow::OnMouse(wxMouseEvent& event)
+wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
 {
+   if(!m_doSendEvents) // nothing to do
+      return;
+
+   wxPaintDC dc( this );
+   PrepareDC( dc );     
    SetFocus();
 
-   if(m_EventId == -1) // nothing to do
-      return;
-   
-   m_FindPos.x = event.GetX();
-   m_FindPos.y = event.GetY();
-   m_FoundObject = (wxLayoutObjectBase *) NULL;
+   wxPoint findPos;
+   findPos.x = dc.DeviceToLogicalX(event.GetX());
+   findPos.y = dc.DeviceToLogicalY(event.GetY());
 
-#ifdef   WXLAYOUT_DEBUG
-   //doesn't work, undefined functions
-   //wxLogTrace("OnMouse: (%d, %d)", m_FindPos.x, m_FindPos.y);
-#endif
-   Refresh();
-   if(m_FoundObject)
+   TRACEMESSAGE(("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
+                 event.GetX(), event.GetY(), findPos.x, findPos.y));
+
+   // find the object at this position
+   wxLayoutObjectBase *obj = m_llist.Find(findPos);
+   if(obj)
    {
-      if(m_EventId != -1)
-      {
-         wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, m_EventId);
-         commandEvent.SetEventObject( this );
-         commandEvent.SetClientData((char *)m_FoundObject);
-         m_ClickPosition = wxPoint(event.GetX(), event.GetY());
-         GetEventHandler()->ProcessEvent(commandEvent);
-      }
+      wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, eventId);
+      commandEvent.SetEventObject( this );
+      commandEvent.SetClientData((char *)obj);
+      GetEventHandler()->ProcessEvent(commandEvent);
    }
 }
 
@@ -112,14 +144,14 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
       break;
    case WXK_END:
       p = m_llist.GetCursor();
-      p.x = m_llist.GetLineLength(m_llist.FindCurrentObject((CoordType *) NULL));
+      p.x = m_llist.GetLineLength(m_llist.FindCurrentObject(NULL));
       m_llist.SetCursor(p);
       break;
    case WXK_DELETE :
       if(event.ControlDown()) // delete to end of line
       {
          help = m_llist.GetLineLength(
-            m_llist.FindCurrentObject((CoordType *) NULL))
+            m_llist.FindCurrentObject(NULL))
             - m_llist.GetCursor().x;
          m_llist.Delete(help ? help : 1);
       }
@@ -127,17 +159,20 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
          m_llist.Delete(1);
       break;
    case WXK_BACK: // backspace
-      if(m_llist.MoveCursor(-1))
+      if(m_llist.MoveCursor(-1)) {
          m_llist.Delete(1);
+      }
       break;
    case WXK_RETURN:
       m_llist.LineBreak();
       break;
-#ifdef WXLAYOUT_DEBUG   
+
+#ifdef WXLAYOUT_DEBUG
    case WXK_F1:
       m_llist.Debug();
       break;
-#endif 
+#endif
+      
    default:
       if(keyCode < 256 && keyCode >= 32)
       {
@@ -147,20 +182,75 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
       }
       break;
    }
-   Refresh();
-   UpdateScrollbars();
+
+   /** Scroll so that cursor is visible! */
+   int x0,y0,x1,y1,ux,uy;
+   ViewStart(&x0,&y0);
+   GetScrollPixelsPerUnit(&ux,&uy);
+   x0*=ux; y0*=uy;
+   GetClientSize(&x1,&y1);
+
+   wxPoint cc = m_llist.GetCursorCoords();
+   int nx = x0, ny = y0;
+   // when within 10% of borders, scroll to center
+   if(cc.y > y0+(9*y1)/10)
+      ny = cc.y - y1/5;
+   else if (cc.y < y0+y1/10)
+   {
+      ny = cc.y-y1/2;
+      if(ny < 0) ny = 0;
+   }
+   if(cc.x > x0+(9*x1)/10)
+      nx = cc.x - x1/5;
+   else if (cc.x < x0+x1/10)
+   {
+      nx = cc.x-x1/2;
+      if(nx < 0) nx = 0;
+   }
+   Scroll(nx,ny);
+   
+   Update();
 }
 
 void
-wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)w)  // or: OnDraw(wxDC& dc)
+wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event))  // or: OnDraw(wxDC& dc)
 {
-   wxPaintDC dc( this );  // only when used as OnPaint for OnDraw we
-   PrepareDC( dc );       // can skip the first two lines
+   wxPaintDC dc( this );
+   PrepareDC( dc );
+
+   DoPaint(dc);
+
+// wxGTK: wxMemoryDC broken?
+#if 0
+   int x0,y0,x1,y1;
+   ViewStart(&x0,&y0);
+   GetSize(&x1,&y1);
+   WXL_VAR(x0); WXL_VAR(y0);
+   WXL_VAR(x1); WXL_VAR(y1);
+   
+   wxMemoryDC(memdc);
+   wxBitmap bm(x1,y1);
+   memdc.SelectObject(bm);
+
+   // make temporary copy and edit this
+   memdc.SetDeviceOrigin(x0,y0);
+   memdc.Blit(x0,y0,x1,y1,&dc,x0,y0,wxCOPY,FALSE);
+   DoPaint(memdc);
+   // blit it back
+   dc.Blit(x0,y0,x1,y1,&memdc,x0,y0,wxCOPY,FALSE);
+#endif
+   
+}
+
+// does the actual painting
+void
+wxLayoutWindow::DoPaint(wxDC &dc)
+{
+   m_llist.EraseAndDraw(dc);
+   m_llist.DrawCursor(dc);
+   // FIXME: not strictly correct, this does only work for changes behind
+   //   the cursor position, not complete redraws
 
-   if(m_EventId != -1) // look for keyclicks
-      m_FoundObject = m_llist.Draw(dc,true,m_FindPos);
-   else
-      m_llist.Draw(dc);
    if(! m_ScrollbarsSet)
    {
       m_ScrollbarsSet = true; // avoid recursion
@@ -173,17 +263,17 @@ wxLayoutWindow::UpdateScrollbars(void)
 {
    CoordType
       max_x, max_y, lineHeight;
-   
+
+   ViewStart(&m_ViewStartX, &m_ViewStartY);
    m_llist.GetSize(&max_x, &max_y, &lineHeight);
-   SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1);
-   EnableScrolling(true,true);
+   SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1,m_ViewStartX,m_ViewStartY,true);
+   //EnableScrolling(true,true);
+   //Scroll(m_ViewStartX, m_ViewStartY);
 }
 
 void
 wxLayoutWindow::Print(void)
 {
-   VAR(wxThePrintSetupData);
-
    wxPostScriptDC   dc("layout.ps",true,this);
    if (dc.Ok() && dc.StartDoc((char *)_("Printing message...")))
    {
index 48111825df2ccbdb91785d925ffa891da7cf77a6..0f5c60611ff474ff59debca2d3e399a9cbdb37c9 100644 (file)
 class wxLayoutWindow : public wxScrolledWindow
 {
 public:
+   /** Constructor.
+       @param parent parent window to display this panel in
+   */
    wxLayoutWindow(wxWindow *parent);
 
+   /* Returns a reference to the wxLayoutList object.
+      @return the list
+   */
    wxLayoutList & GetLayoutList(void) { return m_llist; }
 
    // clears the window and sets default parameters:
@@ -32,38 +38,66 @@ public:
       {
          GetLayoutList().Clear(family,size,style,weight,underline,fg,bg);
          SetBackgroundColour( *GetLayoutList().GetDefaults()->GetBGColour());
+
+         m_bDirty = FALSE;
       }
 
    // callbacks
    // NB: these functions are used as event handlers and must not be virtual
-   //void OnDraw(wxDC &dc);
-   void OnPaint(wxPaintEvent &WXUNUSED(event));
-   void OnMouse(wxMouseEvent& event);
+   void OnPaint(wxPaintEvent &event);
+   
+   void OnLeftMouseClick(wxMouseEvent& event)
+      { OnMouse(WXMENU_LAYOUT_LCLICK, event); }
+   void OnRightMouseClick(wxMouseEvent& event)
+      { OnMouse(WXMENU_LAYOUT_RCLICK, event); }
+   void OnMouseDblClick(wxMouseEvent& event)
+      { OnMouse(WXMENU_LAYOUT_DBLCLICK, event); }
+
    void OnChar(wxKeyEvent& event);
 
+   /// gets called by either Update() or OnPaint()
+   void DoPaint(wxDC &dc);
+
 #ifdef __WXMSW__
    virtual long MSWGetDlgCode();
 #endif //MSW
 
    void UpdateScrollbars(void);
    void Print(void);
-   void SetEventId(int id) { m_EventId = id; }
-   // what for? Caller doesn't even know object's positions in window
-   //wxPoint const &GetClickPosition(void) const { return m_ClickPosition; }
-   virtual ~wxLayoutWindow() {}
-private:
+
+   /// if the flag is true, we send events when user clicks on embedded objects
+   inline void SetMouseTracking(bool doIt = true) { m_doSendEvents = doIt; }
+
+   virtual ~wxLayoutWindow() { }
+
+   // dirty flag access
+   bool IsDirty() const { return m_llist.IsDirty(); }
+   void ResetDirty()    { m_llist.ResetDirty();     }
+
+   
+protected:
+   /// generic function for mouse events processing
+   void OnMouse(int eventId, wxMouseEvent& event);
+
+   /// repaint if needed
+   void Update(void);
+
    /// for sending events
    wxWindow *m_Parent;
-   int m_EventId;
+   bool m_doSendEvents;
+
    /// the layout list to be displayed
    wxLayoutList m_llist;
+
    /// have we already set the scrollbars?
    bool m_ScrollbarsSet;
-   /// if we want to find an object:
-   wxPoint m_FindPos;
-   wxLayoutObjectBase *m_FoundObject;
-   wxPoint m_ClickPosition;
+   /// Where does the current view start?
+   int m_ViewStartX; int m_ViewStartY;
+   
+   /// do we have unsaved data?
+   bool m_bDirty;
 
+private:
    DECLARE_EVENT_TABLE()
 };