Rewrite. Cursor handling better, split Layout() and Draw(), faster.

Printing almost works.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@906 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Karsten Ballüder
1998-10-24 18:08:20 +00:00
parent 01111366c9
commit 0e6c619a1a
6 changed files with 767 additions and 436 deletions

View File

@@ -54,25 +54,16 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
END_EVENT_TABLE() END_EVENT_TABLE()
int orientation = wxPORTRAIT; int orientation = wxPORTRAIT;
MyFrame::MyFrame(void) :
MyFrame::MyFrame(void) :
wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) ) wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) )
{ {
CreateStatusBar( 1 ); CreateStatusBar( 1 );
SetStatusText( "wxLayout by Karsten Ball<6C>der." ); SetStatusText( "wxLayout by Karsten Ball<6C>der." );
wxMenu *file_menu = new wxMenu( "Menu 1" ); wxMenu *file_menu = new wxMenu;
file_menu->Append( ID_CLEAR, "Clear"); file_menu->Append( ID_CLEAR, "Clear");
file_menu->Append( ID_ADD_SAMPLE, "Example"); file_menu->Append( ID_ADD_SAMPLE, "Example");
file_menu->Append( ID_EDIT, "Edit"); file_menu->Append( ID_EDIT, "Edit");
@@ -104,7 +95,7 @@ int orientation = wxPORTRAIT;
SetMenuBar( menu_bar ); SetMenuBar( menu_bar );
m_lwin = new wxLayoutWindow(this); m_lwin = new wxLayoutWindow(this);
m_lwin->SetEventId(ID_CLICK); m_lwin->SetMouseTracking(true);
m_lwin->GetLayoutList().SetEditable(true); m_lwin->GetLayoutList().SetEditable(true);
m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false); m_lwin->Clear(wxROMAN,16,wxNORMAL,wxNORMAL, false);
m_lwin->SetFocus(); m_lwin->SetFocus();
@@ -113,9 +104,11 @@ int orientation = wxPORTRAIT;
void void
MyFrame::AddSampleText(wxLayoutList &llist) MyFrame::AddSampleText(wxLayoutList &llist)
{ {
llist.SetFont(wxROMAN,16,wxNORMAL,wxNORMAL, false);
llist.Insert("--"); llist.Insert("--");
llist.LineBreak(); llist.LineBreak();
llist.SetFont(wxROMAN);
llist.Insert("The quick brown fox jumps over the lazy dog."); llist.Insert("The quick brown fox jumps over the lazy dog.");
llist.LineBreak(); llist.LineBreak();
llist.Insert("Hello "); llist.Insert("Hello ");
@@ -203,7 +196,7 @@ MyFrame::Clear(void)
void MyFrame::Edit(void) void MyFrame::Edit(void)
{ {
wxLayoutList & llist = m_lwin->GetLayoutList(); wxLayoutList & llist = m_lwin->GetLayoutList();
m_lwin->SetEventId(ID_CLICK); //m_lwin->SetEventId(ID_CLICK);
llist.MoveCursor(0); llist.MoveCursor(0);
llist.MoveCursor(5); llist.MoveCursor(5);
@@ -307,8 +300,10 @@ void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
#endif #endif
wxPrinter printer; wxPrinter printer;
wxLayoutPrintout printout( m_lwin->GetLayoutList(),"My printout"); wxLayoutPrintout printout( m_lwin->GetLayoutList(),"My printout");
if (!printer.Print(this, &printout, TRUE)) if (! printer.Print(this, &printout, TRUE))
wxMessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wxOK); wxMessageBox(
"There was a problem printing.\nPerhaps your current printer is not set correctly?",
"Printing", wxOK);
} }
void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnPrintPS(wxCommandEvent& WXUNUSED(event))
@@ -331,7 +326,9 @@ void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event))
printData.SetOrientation(orientation); printData.SetOrientation(orientation);
// Pass two printout objects: for preview, and possible printing. // 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()) if (!preview->Ok())
{ {
delete preview; delete preview;
@@ -443,7 +440,7 @@ bool MyApp::OnInit(void)
{ {
wxFrame *frame = new MyFrame(); wxFrame *frame = new MyFrame();
frame->Show( TRUE ); frame->Show( TRUE );
wxSetAFMPath("/usr/local/src/wxWindows/misc/afm/"); // wxSetAFMPath("/usr/local/src/wxWindows/misc/afm/");
return TRUE; return TRUE;
}; };

View File

@@ -3,7 +3,7 @@
* * * *
* (C) 1998 by Karsten Ball<6C>der (Ballueder@usa.net) * * (C) 1998 by Karsten Ball<6C>der (Ballueder@usa.net) *
* * * *
* $Id$ * * $Id$
*******************************************************************/ *******************************************************************/
/* /*
@@ -16,25 +16,34 @@
- the cursor position is the position before an object, i.e. if the - 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 buffer starts with a text-object, cursor 0,0 is just before the
first character 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__ #ifdef __GNUG__
#pragma implementation "wxllist.h" #pragma implementation "wxllist.h"
#endif #endif
// these two lines are for use in M:
//#include "Mpch.h" //#include "Mpch.h"
//#include "gui/wxllist.h" #ifdef M_BASEDIR
# include "gui/wxllist.h"
#include "wxllist.h" #else
# include "wxllist.h"
#endif
#ifndef USE_PCH #ifndef USE_PCH
# include "iostream.h" # include "iostream.h"
# include <wx/dc.h>
# include <wx/dc.h> # include <wx/postscrp.h>
# include <wx/postscrp.h> # include <wx/print.h>
# include <wx/print.h> # include <wx/log.h>
# include <wx/log.h>
#endif #endif
#define BASELINESTRETCH 12 #define BASELINESTRETCH 12
@@ -46,7 +55,7 @@ static const char *g_aTypeStrings[] =
}; };
# define wxLayoutDebug wxLogDebug # 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_DBG_POINT(p) wxLogDebug(#p ": (%d, %d)", p.x, p.y)
# define WXL_TRACE(f) wxLogDebug(#f ": ") # define WXL_TRACE(f) wxLogDebug(#f ": ")
# define TypeString(t) g_aTypeStrings[t] # define TypeString(t) g_aTypeStrings[t]
@@ -76,6 +85,7 @@ wxLayoutObjectText::wxLayoutObjectText(const String &txt)
m_Text = txt; m_Text = txt;
m_Width = 0; m_Width = 0;
m_Height = 0; m_Height = 0;
m_Position = wxPoint(-1,-1);
} }
@@ -87,22 +97,26 @@ wxLayoutObjectText::GetSize(CoordType *baseLine) const
} }
void void
wxLayoutObjectText::Draw(wxDC &dc, wxPoint position, CoordType baseLine, wxLayoutObjectText::Draw(wxDC &dc)
bool draw) {
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; 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); 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; m_BaseLine = m_Height - descent;
position.y += baseLine-m_BaseLine; if(m_Position.x != position.x || m_Position.y != position.y)
if(draw) m_IsDirty = true;
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
} }
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
@@ -116,25 +130,35 @@ wxLayoutObjectText::Debug(void)
//-------------------------- wxLayoutObjectIcon //-------------------------- wxLayoutObjectIcon
wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon) wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon const &icon)
: m_Icon(icon)
{ {
m_Position = wxPoint(-1,-1);
m_Icon = new wxIcon(icon);
}
wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon)
{
m_Icon = icon;
} }
void void
wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint position, CoordType baseLine, wxLayoutObjectIcon::Draw(wxDC &dc)
bool draw)
{ {
position.y += baseLine - m_Icon->GetHeight(); dc.DrawIcon(m_Icon,m_Position.x, m_Position.y);
if(draw) }
dc.DrawIcon(m_Icon,position.x,position.y);
void
wxLayoutObjectIcon::Layout(wxDC &dc, wxPoint position, CoordType baseLine)
{
if(m_Position.x != position.x || m_Position.y != position.y)
m_IsDirty = true;
m_Position = position;
} }
wxPoint wxPoint
wxLayoutObjectIcon::GetSize(CoordType *baseLine) const wxLayoutObjectIcon::GetSize(CoordType *baseLine) const
{ {
wxASSERT(baseLine); if(baseLine) *baseLine = m_Icon->GetHeight();
*baseLine = m_Icon->GetHeight();
return wxPoint(m_Icon->GetWidth(), m_Icon->GetHeight()); return wxPoint(m_Icon->GetWidth(), m_Icon->GetHeight());
} }
@@ -179,20 +203,24 @@ wxLayoutObjectCmd::GetStyle(void) const
} }
void void
wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint position, CoordType lineHeight, wxLayoutObjectCmd::Draw(wxDC &dc)
bool draw)
{ {
wxASSERT(m_font); wxASSERT(m_font);
// this get called even when draw==false, so that recalculation
// uses right font sizes
dc.SetFont(m_font); dc.SetFont(m_font);
if(m_ColourFG) if(m_ColourFG)
dc.SetTextForeground(*m_ColourFG); dc.SetTextForeground(*m_ColourFG);
if(m_ColourBG) if(m_ColourBG)
dc.SetTextBackground(*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() wxLayoutList::wxLayoutList()
{ {
@@ -262,217 +290,95 @@ wxLayoutList::GetSize(CoordType *max_x, CoordType *max_y,
if(lineHeight) *lineHeight = m_LineHeight; if(lineHeight) *lineHeight = m_LineHeight;
} }
wxLayoutObjectBase * void
wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const wxLayoutList::ResetSettings(wxDC &dc)
&findCoords, int pageNo, bool reallyDraw)
{ {
wxLayoutObjectList::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;
CoordType baseLine = m_FontPtSize;
CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
// where to draw the cursor
wxPoint
cursorPosition = wxPoint(0,0),
cursorSize = wxPoint(1,baseLineSkip);
// the cursor position inside the object
CoordType cursorOffset = 0;
// object under cursor
wxLayoutObjectList::iterator cursorObject = FindCurrentObject(&cursorOffset);
// 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;
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();
position_HeadOfLine = position;
// setting up the default: // setting up the default:
dc.SetTextForeground( *wxBLACK ); dc.SetTextForeground( *wxBLACK );
dc.SetTextBackground( *wxWHITE ); dc.SetTextBackground( *wxWHITE );
dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background
dc.SetFont( *wxNORMAL_FONT ); dc.SetFont( *wxNORMAL_FONT );
//FIXME: who frees the brush, how long does it need to exist?
if(m_DefaultSetting) if(m_DefaultSetting)
m_DefaultSetting->Draw(dc,wxPoint(0,0),0,true); m_DefaultSetting->Draw(dc);
}
// we calculate everything for drawing a line, then rewind to the void
// begin of line and actually draw it wxLayoutList::Layout(wxDC &dc)
i = begin(); {
for(;;) iterator i;
// first object in current line
wxLayoutObjectList::iterator headOfLine;
// where we draw next
wxPoint position, position_HeadOfLine;
// size of last object
wxPoint size;
CoordType baseLine = m_FontPtSize;
CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
CoordType objBaseLine = baseLine;
wxLayoutObjectType type;
// we need to count cursor positions
wxPoint cursorPos = wxPoint(0,0);
wxLayoutObjectBase *cursorObject = NULL; // let's find it again
struct
{ {
recalculate = false; int top, bottom, left, right;
} margins;
margins.top = 0; margins.left = 0;
margins.right = -1;
margins.bottom = -1;
position.y = margins.top;
position.x = margins.left;
ResetSettings(dc);
i = begin();
headOfLine = i;
position_HeadOfLine = position;
do
{
if(i == end()) if(i == end())
break; return;
type = (*i)->GetType(); type = (*i)->GetType();
(*i)->Layout(dc, position, baseLine);
// 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:
size = (*i)->GetSize(&objBaseLine); 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: // calculate next object's position:
position.x += size.x; position.x += size.x;
if(position.x > m_MaxX)
m_MaxX = position.x;
// do we need to increase the line's height? // do we need to increase the line's height?
if(size.y > baseLineSkip) if(size.y > baseLineSkip)
{ {
baseLineSkip = size.y; baseLineSkip = size.y;
recalculate = true; i = headOfLine; position = position_HeadOfLine;
continue;
} }
if(objBaseLine > baseLine) if(objBaseLine > baseLine)
{ {
baseLine = objBaseLine; baseLine = objBaseLine;
recalculate = true; i = headOfLine; position = position_HeadOfLine;
continue;
} }
// now check whether we have finished handling this line: // when we reach here, the coordinates are valid, this part of
if(type == WXLO_TYPE_LINEBREAK || i == tail()) // 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 cursorPos.x = 0; cursorPos.y ++;
{
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;
} }
else
// is it a linebreak? cursorPos.x += (**i).CountPositions();
if(type == WXLO_TYPE_LINEBREAK || i == tail())
// now check whether we have finished handling this line:
if(type == WXLO_TYPE_LINEBREAK && i != tail())
{ {
position.x = margins.left; position.x = margins.left;
position.y += baseLineSkip; position.y += baseLineSkip;
@@ -483,18 +389,150 @@ wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const
headOfLine++; headOfLine++;
position_HeadOfLine = position; 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++; i++;
} }
// draw the cursor while(i != end());
if(m_Editable) m_MaxY = position.y + baseLineSkip;
{
dc.DrawRectangle(cursorPosition.x, cursorPosition.y,
cursorSize.x, cursorSize.y);
}
m_MaxY = position.y;
return foundObject;
} }
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);
}
else if(obj.GetType() == WXLO_TYPE_LINEBREAK)
{
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);
}
}
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
void void
wxLayoutList::Debug(void) wxLayoutList::Debug(void)
@@ -571,13 +609,27 @@ wxLayoutObjectList::iterator
wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset) wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
{ {
wxPoint object = wxPoint(0,0); // runs along the objects wxPoint object = wxPoint(0,0); // runs along the objects
CoordType width; CoordType width = 0;
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i, begin_it;
int go_up;
//#ifdef WXLAYOUT_DEBUG
// wxLayoutDebug("Looking for object at (%d, %d)", cpos->x, cpos->y);
//#endif
#ifdef WXLAYOUT_DEBUG // optimisation: compare to last looked at object:
wxLayoutDebug("Looking for object at (%d, %d)", cpos->x, cpos->y); if(cpos->y > m_FoundCursor.y || (cpos->y == m_FoundCursor.y &&
#endif cpos->x >= m_FoundCursor.x))
for(i = begin(); i != end() && object.y <= cpos->y; i++) 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(); width = (**i).CountPositions();
if(cpos->y == object.y) // a possible candidate if(cpos->y == object.y) // a possible candidate
@@ -587,48 +639,52 @@ wxLayoutList::FindObjectCursor(wxPoint *cpos, CoordType *offset)
if(cpos->x == object.x) if(cpos->x == object.x)
{ {
if(offset) *offset = 0; if(offset) *offset = 0;
return i; return m_FoundIterator = i;
} }
if(offset) *offset=1; if(offset) *offset=1;
cpos->x = object.x; cpos->x = object.x;
return i; return m_FoundIterator = i;
} }
if(cpos->x >= object.x && cpos->x <= object.x+width) // overlap if(cpos->x >= object.x && cpos->x <= object.x+width) // overlap
{ {
if(offset) *offset = cpos->x-object.x; if(offset) *offset = cpos->x-object.x;
#ifdef WXLAYOUT_DEBUG //#ifdef WXLAYOUT_DEBUG
wxLayoutDebug(" found object at (%d, %d), type: %s", // wxLayoutDebug(" found object at (%d, %d), type: %s",
object.x, object.y, TypeString((*i)->GetType())); // object.x, object.y, TypeString((*i)->GetType()));
#endif //#endif
return i; return m_FoundIterator = i;
} }
} }
// no overlap, increment coordinates // no overlap, increment coordinates
object.x += width; object.x += width;
if((**i).GetType() == WXLO_TYPE_LINEBREAK) if((**i).GetType() == WXLO_TYPE_LINEBREAK)
{ {
object.x = 0; object.x = 0;
object.y++; object.y++;
} }
} if(go_up)
#ifdef WXLAYOUT_DEBUG i++;
wxLayoutDebug(" not found"); else
#endif i--;
}//for
//#ifdef WXLAYOUT_DEBUG
// wxLayoutDebug(" not found");
//#endif
// return last object, coordinates of that one: // return last object, coordinates of that one:
i = tail(); i = tail();
if(i == end()) if(i == end())
return i; return m_FoundIterator = i;
if((**i).GetType()==WXLO_TYPE_LINEBREAK) if((**i).GetType()==WXLO_TYPE_LINEBREAK)
{ {
if(offset) if(offset)
*offset = 1; *offset = 1;
return i; return m_FoundIterator = i;
} }
cpos->x = object.x; // would be the coordinate of next object cpos->x = object.x; // would be the coordinate of next object
cpos->y = object.y; cpos->y = object.y;
cpos->x += width; // last object's width cpos->x += width; // last object's width
if(*offset) *offset = cpos->x-object.x; if(*offset) *offset = cpos->x-object.x;
return i; // not found return m_FoundIterator = i; // not found
} }
wxLayoutObjectList::iterator wxLayoutObjectList::iterator
@@ -652,6 +708,8 @@ wxLayoutList::MoveCursor(int dx, int dy)
CoordType offs, lineLength; CoordType offs, lineLength;
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
m_CursorMoved = true;
bool rc = true; // have we moved? bool rc = true; // have we moved?
if(dy > 0 && m_CursorPosition.y < m_MaxLine) if(dy > 0 && m_CursorPosition.y < m_MaxLine)
@@ -744,6 +802,8 @@ wxLayoutList::Delete(CoordType count)
WXL_VAR(count); WXL_VAR(count);
m_bModified = true;
CoordType offs; CoordType offs;
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
@@ -822,11 +882,14 @@ wxLayoutList::Delete(CoordType count)
void void
wxLayoutList::Insert(wxLayoutObjectBase *obj) wxLayoutList::Insert(wxLayoutObjectBase *obj)
{ {
wxASSERT(obj); wxCHECK_RET( obj, "no object to insert" );
m_bModified = true;
CoordType offs; CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs); wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
WXL_TRACE(Insert(obj)); // WXL_TRACE(Insert(obj));
if(i == end()) if(i == end())
push_back(obj); push_back(obj);
@@ -861,6 +924,7 @@ wxLayoutList::Insert(wxLayoutObjectBase *obj)
m_CursorPosition.x += obj->CountPositions(); m_CursorPosition.x += obj->CountPositions();
if(obj->GetType() == WXLO_TYPE_LINEBREAK) if(obj->GetType() == WXLO_TYPE_LINEBREAK)
m_MaxLine++; m_MaxLine++;
m_CursorMoved = true;
} }
void void
@@ -869,11 +933,13 @@ wxLayoutList::Insert(String const &text)
wxLayoutObjectText *tobj = NULL; wxLayoutObjectText *tobj = NULL;
wxLayoutObjectList::iterator j; wxLayoutObjectList::iterator j;
WXL_TRACE(Insert(text)); // WXL_TRACE(Insert(text));
if(! m_Editable) if(! m_Editable)
return; return;
m_bModified = true;
CoordType offs; CoordType offs;
wxLayoutObjectList::iterator i = FindCurrentObject(&offs); wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
@@ -923,24 +989,9 @@ wxLayoutList::Insert(String const &text)
} }
} }
break; 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_CursorPosition.x += strlen(text.c_str());
m_CursorMoved = true;
} }
CoordType CoordType
@@ -972,12 +1023,18 @@ void
wxLayoutList::Clear(int family, int size, int style, int weight, wxLayoutList::Clear(int family, int size, int style, int weight,
int underline, char const *fg, char const *bg) int underline, char const *fg, char const *bg)
{ {
m_bModified = true;
m_CursorMoved = true;
m_dirty = true; // force redraw/recalc
wxLayoutObjectList::iterator i = begin(); wxLayoutObjectList::iterator i = begin();
wxBitmap bm(1,1);
m_CursorMemDC.SelectObject(bm);
while(i != end()) // == while valid while(i != end()) // == while valid
erase(i); erase(i);
// set defaults // set defaults
m_FontPtSize = size; m_FontPtSize = size;
m_FontUnderline = false; m_FontUnderline = false;
m_FontFamily = family; m_FontFamily = family;
@@ -995,9 +1052,13 @@ wxLayoutList::Clear(int family, int size, int style, int weight,
m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10; m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10;
m_MaxX = 0; m_MaxY = 0; m_MaxX = 0; m_MaxY = 0;
m_FoundCursor = wxPoint(0,0);
m_FoundIterator = begin();
if(m_DefaultSetting) if(m_DefaultSetting)
delete m_DefaultSetting; delete m_DefaultSetting;
m_DefaultSetting = new m_DefaultSetting = new
wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle, wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
m_FontWeight,m_FontUnderline, 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 ********************/ /******************** printing stuff ********************/
bool wxLayoutPrintout::OnPrintPage(int page) bool wxLayoutPrintout::OnPrintPage(int page)
{ {
wxDC *dc = GetDC(); wxDC *dc = GetDC();
if (dc) int top, bottom,width,height;
{ if (dc)
m_llist->Draw(*dc,false,wxPoint(0,0),page); {
return TRUE; dc->GetSize(&width, &height);
}
else top = (page - 1) * (9*height)/10;
return FALSE; 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) bool wxLayoutPrintout::OnBeginDocument(int startPage, int endPage)
{ {
if (!wxPrintout::OnBeginDocument(startPage, endPage)) if (!wxPrintout::OnBeginDocument(startPage, endPage))
return FALSE; return false;
return TRUE; return true;
} }
void
wxLayoutPrintout::OnPreparePrinting(void)
{
}
void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) 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. // 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? // 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 *minPage = 0;
*selPageTo = 100; *maxPage = (int)( m_llist->GetSize().y / (float)(0.9*height) + 0.5);
// *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;
*selPageFrom = 1; *selPageFrom = 1;
*selPageTo = *maxPage; *selPageTo = *maxPage;
m_maxPage = *maxPage; m_maxPage = *maxPage;
#endif
} }
bool wxLayoutPrintout::HasPage(int pageNum) bool wxLayoutPrintout::HasPage(int pageNum)
{ {
return pageNum <= 5; // for testing if(m_maxPage != -1)
// return m_maxPage >= pageNum; return pageNum <= m_maxPage;
return true;
} }

View File

@@ -15,10 +15,10 @@
#include "kbList.h" #include "kbList.h"
#include "wx/wx.h" #include "wx/wx.h"
#include "wx/print.h" #include "wx/print.h"
#include "wx/printdlg.h" #include "wx/printdlg.h"
#include "wx/generic/printps.h" #include "wx/generic/printps.h"
#include "wx/generic/prntdlgg.h" #include "wx/generic/prntdlgg.h"
// skip the following defines if embedded in M application // skip the following defines if embedded in M application
#ifdef M_BASEDIR #ifdef M_BASEDIR
@@ -30,6 +30,9 @@
# define WXLAYOUT_DEBUG # define WXLAYOUT_DEBUG
// The wxLayout classes can be compiled with std::string instead of wxString // The wxLayout classes can be compiled with std::string instead of wxString
//# define USE_STD_STRING //# define USE_STD_STRING
# define WXMENU_LAYOUT_LCLICK 1111
# define WXMENU_LAYOUT_RCLICK 1112
# define WXMENU_LAYOUT_DBLCLICK 1113
#endif #endif
#ifdef USE_STD_STRING #ifdef USE_STD_STRING
@@ -62,46 +65,68 @@ class wxFont;
class wxLayoutObjectBase class wxLayoutObjectBase
{ {
public: public:
struct UserData
{
virtual ~UserData() { }
};
/// return the type of this object /// return the type of this object
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_INVALID; } ; 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 dc the wxDC to draw on
@param position where to draw the top left corner @param position where to draw the top left corner
@param baseLine the baseline for alignment, from top of box @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, virtual void Layout(wxDC & dc,
bool draw = true) {}; wxPoint position,
CoordType baseLine) {}
/** Calculates and returns the size of the object. May need to be /** Draws an object.
called twice to work. @param dc the wxDC to draw on
*/
virtual void Draw(wxDC & dc) {}
/** Calculates and returns the size of the object.
@param baseLine pointer where to store the baseline position of @param baseLine pointer where to store the baseline position of
this object (i.e. the height from the top of the box to the this object (i.e. the height from the top of the box to the
baseline) baseline)
@return the size of the object's box in pixels @return the size of the object's box in pixels
*/ */
virtual wxPoint GetSize(CoordType *baseLine) const { return virtual wxPoint GetSize(CoordType * baseLine = NULL) const
wxPoint(0,0); }; { 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 /// returns the number of cursor positions occupied by this object
virtual CoordType CountPositions(void) const { return 1; } virtual CoordType CountPositions(void) const { return 1; }
/// constructor /// constructor
wxLayoutObjectBase() { m_UserData = NULL; } wxLayoutObjectBase() { m_UserData = NULL; }
/// note: any user data will be freed at the time the object is deleted /// delete the user data
virtual ~wxLayoutObjectBase() { if(m_UserData) delete m_UserData; } virtual ~wxLayoutObjectBase() { delete m_UserData; }
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
virtual void Debug(void); virtual void Debug(void);
#endif #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 /** Tells the object about some user data. This data is associated
with the object and will be deleted at destruction time. 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. */ /** Return the user data. */
void * GetUserData(void) const { return m_UserData; } void * GetUserData(void) const { return m_UserData; }
private: private:
/// optional data for application's use /// optional data for application's use
void * m_UserData; UserData *m_UserData;
protected:
wxPoint m_Position;
}; };
/// Define a list type of wxLayoutObjectBase pointers. /// Define a list type of wxLayoutObjectBase pointers.
@@ -112,44 +137,58 @@ KBLIST_DEFINE(wxLayoutObjectList, wxLayoutObjectBase);
class wxLayoutObjectText : public wxLayoutObjectBase class wxLayoutObjectText : public wxLayoutObjectBase
{ {
public: public:
wxLayoutObjectText(const String &txt);
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; }
virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine, virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine);
bool draw = true); virtual void Draw(wxDC &dc);
/** This returns the height and in baseLine the position of the /** This returns the height and in baseLine the position of the
text's baseline within it's box. This is needed to properly text's baseline within it's box. This is needed to properly
align text objects. align text objects.
*/ */
virtual wxPoint GetSize(CoordType *baseLine) const; virtual wxPoint GetSize(CoordType *baseLine = NULL) const;
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
virtual void Debug(void); virtual void Debug(void);
#endif #endif
wxLayoutObjectText(const String &txt);
virtual CoordType CountPositions(void) const { return strlen(m_Text.c_str()); } virtual CoordType CountPositions(void) const { return strlen(m_Text.c_str()); }
virtual bool IsDirty(void) const { return m_IsDirty; }
// for editing: // for editing:
String & GetText(void) { return m_Text; } String & GetText(void) { return m_Text; }
void SetText(String const &text) { m_Text = text; } void SetText(String const &text) { m_Text = text; }
private: private:
String m_Text; String m_Text;
/// size of the box containing text /// size of the box containing text
long m_Width, m_Height; long m_Width, m_Height;
/// the position of the baseline counted from the top of the box /// the position of the baseline counted from the top of the box
long m_BaseLine; long m_BaseLine;
/// coordinates have changed
bool m_IsDirty;
}; };
/// icon/pictures: /// icon/pictures:
class wxLayoutObjectIcon : public wxLayoutObjectBase class wxLayoutObjectIcon : public wxLayoutObjectBase
{ {
public: 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 *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: private:
wxIcon *m_Icon; wxIcon *m_Icon;
/// coordinates have changed
bool m_IsDirty;
}; };
/// for export to html: /// for export to html:
@@ -166,8 +205,8 @@ class wxLayoutObjectCmd : public wxLayoutObjectBase
{ {
public: public:
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; }
virtual void Draw(wxDC &dc, wxPoint position, CoordType baseLine, virtual void Draw(wxDC &dc);
bool draw = true); virtual void Layout(wxDC &dc, wxPoint position, CoordType baseLine);
wxLayoutObjectCmd(int size, int family, int style, int weight, wxLayoutObjectCmd(int size, int family, int style, int weight,
bool underline, bool underline,
wxColour const *fg, wxColour const *bg); wxColour const *fg, wxColour const *bg);
@@ -212,44 +251,76 @@ public:
/// adds an object: /// adds an object:
void AddObject(wxLayoutObjectBase *obj); void AddObject(wxLayoutObjectBase *obj);
/// adds a text object
void AddText(String const &txt); void AddText(String const &txt);
/// adds a line break
void LineBreak(void); void LineBreak(void);
/// sets font parameters
void SetFont(int family, int size, int style, void SetFont(int family, int size, int style,
int weight, int underline, int weight, int underline,
wxColour const *fg, wxColour const *fg,
wxColour const *bg); wxColour const *bg);
/// sets font parameters, colours by name
void SetFont(int family=-1, int size = -1, int style=-1, void SetFont(int family=-1, int size = -1, int style=-1,
int weight=-1, int underline = -1, int weight=-1, int underline = -1,
char const *fg = (const char *) NULL, char const *fg = NULL,
char const *bg = (const char *) NULL); char const *bg = NULL);
/// set font family
inline void SetFontFamily(int family) { SetFont(family); } inline void SetFontFamily(int family) { SetFont(family); }
/// set font size
inline void SetFontSize(int size) { SetFont(-1,size); } inline void SetFontSize(int size) { SetFont(-1,size); }
/// set font style
inline void SetFontStyle(int style) { SetFont(-1,-1,style); } inline void SetFontStyle(int style) { SetFont(-1,-1,style); }
/// set font weight
inline void SetFontWeight(int weight) { SetFont(-1,-1,-1,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 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 @param findObject if true, return the object occupying the
position specified by coords position specified by coords
@param coords position where to find the object @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) 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 @return if findObject == true, the object or NULL
*/ */
wxLayoutObjectBase *Draw(wxDC &dc, bool findObject = false, void Layout(wxDC &dc);
wxPoint const &coords = wxPoint(0,0),
int pageNo = -1, bool reallyDraw = true); /** 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 #ifdef WXLAYOUT_DEBUG
void Debug(void); void Debug(void);
void ShowCurrentObject(); void ShowCurrentObject();
#endif #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: /// for access by wxLayoutWindow:
void GetSize(CoordType *max_x, CoordType *max_y, void GetSize(CoordType *max_x, CoordType *max_y,
CoordType *lineHeight); CoordType *lineHeight);
@@ -264,7 +335,13 @@ public:
/// move cursor, returns true if it could move to the desired position /// move cursor, returns true if it could move to the desired position
bool MoveCursor(int dx = 0, int dy = 0); bool MoveCursor(int dx = 0, int dy = 0);
void SetCursor(wxPoint const &p) { m_CursorPosition = p; } 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; } 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 /// delete one or more cursor positions
void Delete(CoordType count = 1); void Delete(CoordType count = 1);
void Insert(String const &text); void Insert(String const &text);
@@ -275,13 +352,15 @@ public:
/// return a pointer to the default settings: /// return a pointer to the default settings:
wxLayoutObjectCmd const *GetDefaults(void) const { return m_DefaultSetting ; } 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 // 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 // only used to decide whether we are before or after linebreak
CoordType GetLineLength(wxLayoutObjectList::iterator i, CoordType GetLineLength(wxLayoutObjectList::iterator i,
CoordType offs = 0); CoordType offs = 0);
wxLayoutPrintout *MakePrintout(wxString const &name); wxLayoutPrintout *MakePrintout(wxString const &name);
/// Return maximum X,Y coordinates
wxPoint GetSize(void) const { return wxPoint(m_MaxX, m_MaxY); }
//@} //@}
protected: protected:
/// font parameters: /// font parameters:
@@ -296,6 +375,11 @@ protected:
/// needs recalculation? /// needs recalculation?
bool m_dirty; bool m_dirty;
/// cursor moved
bool m_CursorMoved;
/// needs saving (i.e., was modified?)
bool m_bModified;
// the currently updated line: // the currently updated line:
/// where do we draw next: /// where do we draw next:
@@ -308,28 +392,46 @@ protected:
CoordType m_MaxY; CoordType m_MaxY;
//---- this is needed for editing: //---- this is needed for editing:
/// where is the text cursor: /// where is the text cursor (column,line):
wxPoint m_CursorPosition; 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 /// which is the last line
CoordType m_MaxLine; CoordType m_MaxLine;
/// can we edit it? /// can we edit it?
bool m_Editable; bool m_Editable;
/// find the object to the cursor position and returns the offset /// find the object to the cursor position and returns the offset
/// in there /// 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 class wxLayoutPrintout: public wxPrintout
{ {
public: 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; } { m_llist = &llist; m_maxPage = 0; }
bool OnPrintPage(int page); bool OnPrintPage(int page);
bool HasPage(int page); bool HasPage(int page);
bool OnBeginDocument(int startPage, int endPage); bool OnBeginDocument(int startPage, int endPage);
void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int
*selPageTo); *selPageTo);
void OnPreparePrinting(void);
private: private:
wxLayoutList *m_llist; wxLayoutList *m_llist;
int m_maxPage; int m_maxPage;

View File

@@ -10,11 +10,28 @@
# pragma implementation "wxlparser.h" # pragma implementation "wxlparser.h"
#endif #endif
#include "wxllist.h" //#include "Mpch.h"
#include "wxlparser.h" #ifdef M_BASEDIR
# include "gui/wxllist.h"
# include "gui/wxlparser.h"
#else
# include "wxllist.h"
# include "wxlparser.h"
#endif
#define BASE_SIZE 12 #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) void wxLayoutImportText(wxLayoutList &list, String const &str)
{ {
char * cptr = (char *)str.c_str(); // string gets changed only temporarily char * cptr = (char *)str.c_str(); // string gets changed only temporarily
@@ -23,15 +40,22 @@ void wxLayoutImportText(wxLayoutList &list, String const &str)
for(;;) for(;;)
{ {
begin = cptr++; begin = cptr;
while(*cptr && *cptr != '\n') while( *cptr && !IsEndOfLine(cptr) )
cptr++; cptr++;
backup = *cptr; backup = *cptr;
*cptr = '\0'; *cptr = '\0';
list.Insert(begin); list.Insert(begin);
*cptr = backup; *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(); list.LineBreak();
}
else if(backup == '\0') // reached end of string else if(backup == '\0') // reached end of string
break; break;
cptr++; cptr++;
@@ -168,8 +192,9 @@ String wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
*str += '\n'; *str += '\n';
break; break;
case WXLO_TYPE_CMD: case WXLO_TYPE_CMD:
//wxASSERT(mode == WXLO_EXPORT_AS_HTML,"reached cmd object in text mode") wxASSERT_MSG( mode == WXLO_EXPORT_AS_HTML,
assert(mode == WXLO_EXPORT_AS_HTML); "reached cmd object in text mode" );
*str += wxLayoutExportCmdAsHTML(*(wxLayoutObjectCmd const *str += wxLayoutExportCmdAsHTML(*(wxLayoutObjectCmd const
*)*from, &s_si); *)*from, &s_si);
break; break;

View File

@@ -10,14 +10,27 @@
# pragma implementation "wxlwindow.h" # pragma implementation "wxlwindow.h"
#endif #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) BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
EVT_PAINT (wxLayoutWindow::OnPaint) EVT_PAINT (wxLayoutWindow::OnPaint)
EVT_CHAR (wxLayoutWindow::OnChar) 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() END_EVENT_TABLE()
wxLayoutWindow::wxLayoutWindow(wxWindow *parent) wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
@@ -26,7 +39,15 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
{ {
m_ScrollbarsSet = false; 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__ #ifdef __WXMSW__
@@ -38,34 +59,45 @@ wxLayoutWindow::MSWGetDlgCode()
} }
#endif //MSW #endif //MSW
void
wxLayoutWindow::Update(void)
{
wxClientDC dc(this);
PrepareDC(dc);
if(IsDirty())
{
DoPaint(dc);
UpdateScrollbars();
ResetDirty();
}
m_llist.DrawCursor(dc);
}
void void
wxLayoutWindow::OnMouse(wxMouseEvent& event) wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
{ {
if(!m_doSendEvents) // nothing to do
return;
wxPaintDC dc( this );
PrepareDC( dc );
SetFocus(); SetFocus();
if(m_EventId == -1) // nothing to do wxPoint findPos;
return; findPos.x = dc.DeviceToLogicalX(event.GetX());
findPos.y = dc.DeviceToLogicalY(event.GetY());
m_FindPos.x = event.GetX();
m_FindPos.y = event.GetY();
m_FoundObject = (wxLayoutObjectBase *) NULL;
#ifdef WXLAYOUT_DEBUG TRACEMESSAGE(("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
//doesn't work, undefined functions event.GetX(), event.GetY(), findPos.x, findPos.y));
//wxLogTrace("OnMouse: (%d, %d)", m_FindPos.x, m_FindPos.y);
#endif // find the object at this position
Refresh(); wxLayoutObjectBase *obj = m_llist.Find(findPos);
if(m_FoundObject) if(obj)
{ {
if(m_EventId != -1) wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, eventId);
{ commandEvent.SetEventObject( this );
wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, m_EventId); commandEvent.SetClientData((char *)obj);
commandEvent.SetEventObject( this ); GetEventHandler()->ProcessEvent(commandEvent);
commandEvent.SetClientData((char *)m_FoundObject);
m_ClickPosition = wxPoint(event.GetX(), event.GetY());
GetEventHandler()->ProcessEvent(commandEvent);
}
} }
} }
@@ -112,14 +144,14 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
break; break;
case WXK_END: case WXK_END:
p = m_llist.GetCursor(); 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); m_llist.SetCursor(p);
break; break;
case WXK_DELETE : case WXK_DELETE :
if(event.ControlDown()) // delete to end of line if(event.ControlDown()) // delete to end of line
{ {
help = m_llist.GetLineLength( help = m_llist.GetLineLength(
m_llist.FindCurrentObject((CoordType *) NULL)) m_llist.FindCurrentObject(NULL))
- m_llist.GetCursor().x; - m_llist.GetCursor().x;
m_llist.Delete(help ? help : 1); m_llist.Delete(help ? help : 1);
} }
@@ -127,17 +159,20 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
m_llist.Delete(1); m_llist.Delete(1);
break; break;
case WXK_BACK: // backspace case WXK_BACK: // backspace
if(m_llist.MoveCursor(-1)) if(m_llist.MoveCursor(-1)) {
m_llist.Delete(1); m_llist.Delete(1);
}
break; break;
case WXK_RETURN: case WXK_RETURN:
m_llist.LineBreak(); m_llist.LineBreak();
break; break;
#ifdef WXLAYOUT_DEBUG
#ifdef WXLAYOUT_DEBUG
case WXK_F1: case WXK_F1:
m_llist.Debug(); m_llist.Debug();
break; break;
#endif #endif
default: default:
if(keyCode < 256 && keyCode >= 32) if(keyCode < 256 && keyCode >= 32)
{ {
@@ -147,20 +182,75 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
} }
break; 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 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 wxPaintDC dc( this );
PrepareDC( dc ); // can skip the first two lines 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) if(! m_ScrollbarsSet)
{ {
m_ScrollbarsSet = true; // avoid recursion m_ScrollbarsSet = true; // avoid recursion
@@ -173,17 +263,17 @@ wxLayoutWindow::UpdateScrollbars(void)
{ {
CoordType CoordType
max_x, max_y, lineHeight; max_x, max_y, lineHeight;
ViewStart(&m_ViewStartX, &m_ViewStartY);
m_llist.GetSize(&max_x, &max_y, &lineHeight); m_llist.GetSize(&max_x, &max_y, &lineHeight);
SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1); SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1,m_ViewStartX,m_ViewStartY,true);
EnableScrolling(true,true); //EnableScrolling(true,true);
//Scroll(m_ViewStartX, m_ViewStartY);
} }
void void
wxLayoutWindow::Print(void) wxLayoutWindow::Print(void)
{ {
VAR(wxThePrintSetupData);
wxPostScriptDC dc("layout.ps",true,this); wxPostScriptDC dc("layout.ps",true,this);
if (dc.Ok() && dc.StartDoc((char *)_("Printing message..."))) if (dc.Ok() && dc.StartDoc((char *)_("Printing message...")))
{ {

View File

@@ -21,8 +21,14 @@
class wxLayoutWindow : public wxScrolledWindow class wxLayoutWindow : public wxScrolledWindow
{ {
public: public:
/** Constructor.
@param parent parent window to display this panel in
*/
wxLayoutWindow(wxWindow *parent); wxLayoutWindow(wxWindow *parent);
/* Returns a reference to the wxLayoutList object.
@return the list
*/
wxLayoutList & GetLayoutList(void) { return m_llist; } wxLayoutList & GetLayoutList(void) { return m_llist; }
// clears the window and sets default parameters: // clears the window and sets default parameters:
@@ -32,38 +38,66 @@ public:
{ {
GetLayoutList().Clear(family,size,style,weight,underline,fg,bg); GetLayoutList().Clear(family,size,style,weight,underline,fg,bg);
SetBackgroundColour( *GetLayoutList().GetDefaults()->GetBGColour()); SetBackgroundColour( *GetLayoutList().GetDefaults()->GetBGColour());
m_bDirty = FALSE;
} }
// callbacks // callbacks
// NB: these functions are used as event handlers and must not be virtual // NB: these functions are used as event handlers and must not be virtual
//void OnDraw(wxDC &dc); void OnPaint(wxPaintEvent &event);
void OnPaint(wxPaintEvent &WXUNUSED(event));
void OnMouse(wxMouseEvent& 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); void OnChar(wxKeyEvent& event);
/// gets called by either Update() or OnPaint()
void DoPaint(wxDC &dc);
#ifdef __WXMSW__ #ifdef __WXMSW__
virtual long MSWGetDlgCode(); virtual long MSWGetDlgCode();
#endif //MSW #endif //MSW
void UpdateScrollbars(void); void UpdateScrollbars(void);
void Print(void); void Print(void);
void SetEventId(int id) { m_EventId = id; }
// what for? Caller doesn't even know object's positions in window /// if the flag is true, we send events when user clicks on embedded objects
//wxPoint const &GetClickPosition(void) const { return m_ClickPosition; } inline void SetMouseTracking(bool doIt = true) { m_doSendEvents = doIt; }
virtual ~wxLayoutWindow() {}
private: 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 /// for sending events
wxWindow *m_Parent; wxWindow *m_Parent;
int m_EventId; bool m_doSendEvents;
/// the layout list to be displayed /// the layout list to be displayed
wxLayoutList m_llist; wxLayoutList m_llist;
/// have we already set the scrollbars? /// have we already set the scrollbars?
bool m_ScrollbarsSet; bool m_ScrollbarsSet;
/// if we want to find an object: /// Where does the current view start?
wxPoint m_FindPos; int m_ViewStartX; int m_ViewStartY;
wxLayoutObjectBase *m_FoundObject;
wxPoint m_ClickPosition; /// do we have unsaved data?
bool m_bDirty;
private:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };