00001 /*! \file cantext.h 00002 \brief a2dText derived from a2dCanvasObject, holds multiline text 00003 \author Klaas Holwerda, Erik van der Wal 00004 00005 Copyright: 2000-2004 (c) Klaas Holwerda 00006 00007 Licence: wxWidgets Licence 00008 00009 RCS-ID: $Id: cantext.h,v 1.29 2009/07/16 20:06:33 titato Exp $ 00010 */ 00011 00012 #ifndef __WXCANTEXT_H__ 00013 #define __WXCANTEXT_H__ 00014 00015 #include "wx/canvas/canobj.h" 00016 00017 /*! \defgroup textrelated Text related classes 00018 */ 00019 00020 //! a2dText is an abstract base class. 00021 /*! 00022 The text is filled with a background if a2dFill != *a2dTRANSPARENT_FILL 00023 The fill colour is the Colour of the a2dFill. 00024 The a2dStroke colour is the colour used for the text itself. 00025 00026 The text can be aligned, see SetAlignment() for info. 00027 \par User editing keys: 00028 00029 <TABLE border=0 cellpadding=0 cellspacing=0> 00030 <tr><td colspan=2><br><b>Cursor movement</b></td></tr><br> 00031 <tr><td colspan=2>Text selection can be done by pressing the Shift key, simultaneously with one of the following keys.<br></td></tr><br> 00032 00033 <TR><TD class="memItemLeft" nowrap>Cursor up/down</TD><TD class="memItemRight"> Move cursor one line up/down.</TD></TR> 00034 <TR><TD class="memItemLeft" nowrap>Cursor Left / Ctrl + B</TD><TD class="memItemRight"> Move cursor one character to the left.</TD></TR> 00035 <TR><TD class="memItemLeft" nowrap>Cursor Right / Ctrl + F</TD><TD class="memItemRight"> Move cursor one character to the right.</TD></TR> 00036 <TR><TD class="memItemLeft" nowrap>Ctrl + Left / Alt + B</TD><TD class="memItemRight"> Move cursor to start of (previous) word.</TD></TR> 00037 <TR><TD class="memItemLeft" nowrap>Ctrl + Right / Alt + F</TD><TD class="memItemRight"> Move cursor to start of next word.</TD></TR> 00038 <TR><TD class="memItemLeft" nowrap>Home / Ctrl + A</TD><TD class="memItemRight"> Move to start of line</TD></TR> 00039 <TR><TD class="memItemLeft" nowrap>End / Ctrl + E</TD><TD class="memItemRight"> Move to end of line</TD></TR> 00040 <TR><TD class="memItemLeft" nowrap>Ctrl + N</TD><TD class="memItemRight"> Move to start of next line.</TD></TR> 00041 <TR><TD class="memItemLeft" nowrap>Ctrl + P</TD><TD class="memItemRight"> Move to start of previous line.</TD></TR> 00042 <TR><TD class="memItemLeft" nowrap>Ctrl + Home</TD><TD class="memItemRight"> Move to start of text.</TD></TR> 00043 <TR><TD class="memItemLeft" nowrap>Ctrl + End</TD><TD class="memItemRight"> Move to end of text.</TD></TR> 00044 00045 <TR><TD colspan=2><br><b>Deletion</b></TD></TR><br> 00046 <TR><TD colspan=2>If part of the text is selected, deleting it will take precedence over the following keys.<br></TD></TR><br> 00047 00048 <TR><TD class="memItemLeft" nowrap>Backspace / Ctrl + H</TD><TD class="memItemRight"> Delete previous character.</TD></TR><br> 00049 <TR><TD class="memItemLeft" nowrap>Delete / Ctrl + D</TD><TD class="memItemRight"> Delete next character.</TD></TR><br> 00050 <TR><TD class="memItemLeft" nowrap>Ctrl + Backspace / Ctrl + W</TD><TD class="memItemRight"> Delete to start of (previous) word.</TD></TR><br> 00051 <TR><TD class="memItemLeft" nowrap>Ctrl + Delete / Alt + D</TD><TD class="memItemRight"> Delete to start of next word.</TD></TR><br> 00052 <TR><TD class="memItemLeft" nowrap>Ctrl + K</TD><TD class="memItemRight"> Delete to end of line.</TD></TR><br> 00053 <TR><TD class="memItemLeft" nowrap>Ctrl + U</TD><TD class="memItemRight"> Delete current line</TD></TR><br> 00054 00055 <TR><TD colspan=2><br><b>Clipboard<br></b></TD></TR><br> 00056 00057 <TR><TD class="memItemLeft" nowrap>Ctrl + C / Ctrl + Insert</TD><TD class="memItemRight"> Copy text to clipboard.</TD></TR><br> 00058 <TR><TD class="memItemLeft" nowrap>Ctrl + V / Shift + Insert</TD><TD class="memItemRight"> Paste text from clipboard.</TD></TR><br> 00059 <TR><TD class="memItemLeft" nowrap>Ctrl + X / Shift + Delete</TD><TD class="memItemRight"> Cut text to clipboard.</TD></TR><br> 00060 00061 <TR><TD colspan=2><br><b>Text alignment</b></TD></TR><br> 00062 <TR><TD colspan=2>Num lock should be on to use these keys.<br></TD></TR><br> 00063 00064 <TR><TD class="memItemLeft" nowrap>Ctrl + Keypad 1..9</TD><TD class="memItemRight"> Align the text to a different direction.</TD></TR><br> 00065 <TR><TD class="memItemLeft" nowrap>Ctrl + Keypad 0</TD><TD class="memItemRight"> Toggle between bounding box and text alignment.</TD></TR><br> 00066 00067 </TABLE> 00068 00069 \bug EW: Solve behaviour when having a stretched affine matrix. Actually this bug is caused by 00070 the drawing of the text (which cannot be stretched). Maybe even prevent stretching. 00071 \todo EW: How should up-down key react with reversed y-axis? 00072 \todo EW: Undo while text editing? 00073 00074 Proper constructors for several cases. 00075 \code 00076 a2dText( text, x, y, a2dFont( fontfile, size ) ); 00077 00078 a2dText( text, x, y, a2dFont( wxfont, size, alignment), angle, up ); 00079 00080 00081 a2dText( text, x, y, a2dFont( wxfont, size, alignment), 0.0, up ); 00082 00083 text->SetFont( a2dFont( wxfont, text->GetTextHeight(), text->GetAlignment() ) ); 00084 00085 text->SetFont( a2dFont( wxfont, size, text->GetAlignment() ) ); 00086 \endcode 00087 00088 \ingroup canvasobject 00089 \ingroup textrelated 00090 */ 00091 00092 class A2DCANVASDLLEXP a2dText: public a2dCanvasObject 00093 { 00094 public: 00095 enum a2dTextFlags 00096 { 00097 //! Allows multiple lines of text 00098 a2dCANOBJTEXT_MULTILINE = 1 << 1, 00099 //! Todo: The text will not be user-editable, but is selectable 00100 a2dCANOBJTEXT_READONLY = 1 << 2, 00101 //! show the caret 00102 a2dCANOBJTEXT_CARETVISIBLE = 1 << 3, 00103 //! next line is higher in Y if set 00104 a2dCANOBJTEXT_NEXTLINEUP = 1 << 4, 00105 //! Text is always readible from the bottom right. 00106 a2dCANOBJTEXT_ENGINEERING = 1 << 5, 00107 //! disable background drawing 00108 a2dCANOBJTEXT_BACKGROUND = 1 << 6, 00109 //! allow draw a frame rect around a text 00110 a2dCANOBJTEXT_FRAME = 1 << 7, 00111 a2dCANVASTEXT_DEFAULTFLAGS = a2dCANOBJTEXT_MULTILINE 00112 | a2dCANOBJTEXT_CARETVISIBLE 00113 | a2dCANOBJTEXT_NEXTLINEUP 00114 }; 00115 00116 public: 00117 A2D_DECLARE_EVENT_TABLE() 00118 DECLARE_DYNAMIC_CLASS(a2dText) 00119 00120 //! constructor 00121 /*! 00122 create text object at (0,0) text is set to "not specified" if not given 00123 */ 00124 a2dText( const wxString &text = wxT("not specified")); 00125 00126 //! constructor 00127 /*! 00128 \param text text to display 00129 \param x x start 00130 \param y y start 00131 \param font a2dFont to use 00132 \param angle angle in degrees 00133 \param up if true next line is higher in Y else lower 00134 \param alignment Alignment of the text. (See SetAlignment) 00135 */ 00136 a2dText( const wxString &text, double x, double y, 00137 const a2dFont& font = *a2dDEFAULT_CANVASFONT, double angle = 0.0, 00138 bool up = false, int alignment = a2dDEFAULT_ALIGNMENT ); 00139 00140 protected: 00141 //! copy constructor 00142 a2dText( const a2dText &other, CloneOptions options ); 00143 00144 public: 00145 //! Destructor 00146 ~a2dText(); 00147 00148 //! Clone this object and return a pointer to the new object. 00149 virtual a2dObject* Clone( CloneOptions options ) const 00150 { return new a2dText( *this, options ); } 00151 00152 public: 00153 00154 //! get the number of lines in the text 00155 int GetLines() const; 00156 00157 //! get lines into array, return number of lines 00158 int GetAsArray( wxArrayString& array ); 00159 00160 //! get the number of lines in the text 00161 wxString GetLine(int line) const; 00162 00163 //! set the text for the object '\n' in string means new line 00164 inline void SetText( const wxString& text ) 00165 { m_text = text; m_utbbox_changed = true; SetPending(true); } 00166 //! get the text of the object '\n' in string means new line 00167 inline wxString GetText() const { return m_text; } 00168 00169 //! set text height in world coordinates 00170 inline void SetTextHeight( double height ) 00171 { m_font.SetSize(height); m_utbbox_changed = true; SetPending(true); } 00172 //! get text height in world coordinates 00173 inline double GetTextHeight() const { return m_font.GetSize(); } 00174 00175 //! Height in world coordinates of one line 00176 inline double GetLineHeight() const { return m_font.GetLineHeight(); } 00177 00178 //! Set Space in world coordinates between two lines 00179 inline void SetLineSpacing( double linespace ) 00180 { m_linespace = linespace; m_utbbox_changed = true; SetPending(true); } 00181 //! Get Space in world coordinates between two lines 00182 inline double GetLineSpacing() const { return m_linespace; } 00183 00184 //! Set the text flags 00185 inline void SetTextFlags( unsigned int textflags ) { m_textflags = textflags; m_utbbox_changed = true; } 00186 //! Get the text flags 00187 inline unsigned int GetTextFlags() const { return m_textflags; } 00188 00189 //! Set if multiple lines of text are allowed. 00190 void SetMultiLine(bool multiline = true); 00191 //! True if multiple lines of text are allowed. 00192 inline bool GetMultiLine() const 00193 { return (m_textflags & a2dCANOBJTEXT_MULTILINE) != 0; } 00194 00195 //! Set if text is readonly 00196 void SetReadOnly(bool readonly = true); 00197 //! True if text is readonly. 00198 inline bool GetReadOnly() 00199 { return (m_textflags & a2dCANOBJTEXT_READONLY) != 0; } 00200 00201 //! next line is higher in Y if true or lower if false 00202 void SetNextLineDirection( bool up ); 00203 //! next line is higher in Y if true or lower if false 00204 inline bool GetNextLineDirection() const 00205 { return (m_textflags & a2dCANOBJTEXT_NEXTLINEUP) != 0; } 00206 00207 //! Keep text readible from the bottom right. 00208 void SetEngineeringText( bool engineering = true ); 00209 //! Is text always readible from the bottom right. 00210 inline bool GetEngineeringText() const 00211 { return ( m_textflags & a2dCANOBJTEXT_ENGINEERING ) != 0; } 00212 00213 //! Set if a background will be drawn. 00214 /*! 00215 When a layer style is used with a non transparent fill, 00216 overlapping text is disturbing in case background overlaps other text. 00217 By setting this flag false the background is set transparent, even if a private fill style is used. 00218 Of course one can set the object to use a transparent fill, but this takes memory. 00219 */ 00220 void SetBackGround(bool background = true); 00221 //! \see SetBackGround() 00222 inline bool GetBackGround() const 00223 { return ( m_textflags & a2dCANOBJTEXT_BACKGROUND ) != 0; } 00224 00225 //! Set if a frame rect will be drawn. 00226 /*! 00227 00228 */ 00229 void SetDrawFrame(bool frame = true); 00230 //! \see SetDrawFrame() 00231 inline bool GetDrawFrame() const 00232 { return ( m_textflags & a2dCANOBJTEXT_FRAME ) != 0; } 00233 00234 //! set font for text 00235 /*! This class takes care of deleting the font 00236 \param font The font to set 00237 \param lineSpaceFactor The m_linespace will be set to font.GetSize() * lineSpaceFactor 00238 */ 00239 void SetFont( const a2dFont& font, double lineSpaceFactor = 0.1 ); 00240 //! get font for text 00241 /*! Returns a pointer to the current font. If you need a copy, use (a2dFont) GetFont()->Clone(flat_copy). 00242 */ 00243 inline a2dFont GetFont() const { return m_font; } 00244 00245 //! set position of caret (-1 means off) 00246 inline void SetCaret( int position ) 00247 { m_caret = position; SetPending(true); } 00248 //! Get position of caret (-1 means off) 00249 inline int GetCaret() const { return m_caret; } 00250 00251 //! Set caret to the character closest to the position 00252 /*! \param ic iterative context 00253 \param x (mouse pointer) x-coordinate in absolute world coordinates 00254 \param y (mouse pointer) y-coordinate in absolute world coordinates 00255 \return True if mouse-position was within this object 00256 */ 00257 bool SetCaret( a2dIterC& ic, double x, double y ); 00258 00259 //! set caret on or off 00260 void SetCaretShow( bool visible = true ); 00261 //! return true if caret is visible 00262 inline bool GetCaretShow() const 00263 { return (m_textflags & a2dCANOBJTEXT_CARETVISIBLE) != 0; } 00264 00265 //! Set the position of the anchor point w.r.t the text. 00266 /*! \param alignment sets the direction of the anchor point. The direction can be set like e.g. 00267 wxCENTRE, wxLEFT, wxMINX | wxMAXY. Another setting is wxBBOX, which sets the anchor point not 00268 at the corners of the actual text, but at the corrners of the bounding box of each line. 00269 Not specifying either a horizontal or vertical position will default to the centre. So only 00270 specifying wxLEFT corresponds to the middle-left position. 00271 <!-- view picture using monospaced font --> 00272 \code 00273 wxCENTRE 00274 +-----^-----+ wxBBOX|wxTOP 00275 wxTOP +------#----+ 00276 | # | 00277 wxCENTER | #### #### | 00278 |# # # #| wxBBOX|wxCENTER 00279 wxBOTTOM +-####-#---#+ 00280 | # | 00281 | ### | 00282 +-----v-----+ wxBBOX|wxBOTTOM 00283 wxLEFT wxRIGHT 00284 \endcode 00285 00286 \remark 00287 - Although it seems more logical to position the text w.r.t the anchor point, this would leed 00288 to some non-intuitive situations, like using wxLEFT for right aligned text. 00289 - The types wxMINY and wxMAXY are created, because the definition of top and bottom 00290 are unknown because the orientation of the y-axis is only known to views and not to the 00291 component itself. To be consistent, wxMINX and wxMAXX are created as well. 00292 */ 00293 inline void SetAlignment(int alignment) 00294 { if(m_alignment != alignment) { 00295 m_alignment = alignment; m_utbbox_changed = true; SetPending(true); } } 00296 //! Get the position of the anchor point w.r.t the text 00297 /*! \return The alignment setting. 00298 */ 00299 inline int GetAlignment() const 00300 { return m_alignment; } 00301 00302 bool GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double x, double y ); 00303 00304 bool AdjustPinLocation(); 00305 00306 //! return text as a vector path, where text outline is converted to polyline or polygons. 00307 a2dCanvasObjectList* GetAsCanvasVpaths( bool transform = true ); 00308 00309 #if wxART2D_USE_CVGIO 00310 //! Write object specific CVG data 00311 virtual void DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite ); 00312 00313 //! Load object specific CVG data 00314 void DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts ); 00315 #endif //wxART2D_USE_CVGIO 00316 00317 static a2dPropertyIdFont* PROPID_Font; 00318 00319 DECLARE_PROPERTIES() 00320 00321 protected: 00322 00323 bool DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox ); 00324 00325 //! Render derived object 00326 virtual void DoRender( a2dIterC& ic, OVERLAP clipparent ); 00327 00328 virtual bool DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent ); 00329 00330 //! Get boundingbox without the affine matrix transform included. 00331 /*! \return The boundingbox. 00332 */ 00333 virtual a2dBoundingBox DoGetUnTransformedBbox( a2dBboxFlags flags = a2dCANOBJ_BBOX_NON ) const; 00334 00335 //! Set caret to the character closest to the position 00336 /*! 00337 \param xh (mouse pointer) x-coordinate in world coordinates 00338 \param yh (mouse pointer) y-coordinate in world coordinates 00339 */ 00340 void SetCaretUntransformed( double xh, double yh ); 00341 00342 //! Calculate a new affine, so text is always readible from the bottom right. 00343 a2dAffineMatrix GetEngineeringTransform( a2dIterC& ic ); 00344 00345 virtual bool DoStartEdit( wxUint16 editmode, wxEditStyle editstyle ); 00346 00347 virtual void DoEndEdit(); 00348 00349 void OnChar(wxKeyEvent& event); 00350 00351 void OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event ); 00352 00353 void OnHandleEvent(a2dHandleMouseEvent &event); 00354 00355 const a2dFont& MX_GetFont() const { return m_font; } 00356 void MX_SetFont( const a2dFont& value ) { m_font = value; } 00357 00358 //! font 00359 a2dFont m_font; 00360 00361 //! space between the lines 00362 double m_linespace; 00363 00364 //! the text to display 00365 wxString m_text; 00366 00367 //! contains several text flags. 00368 unsigned int m_textflags; 00369 00370 //! position of caret within text string 00371 int m_caret; 00372 00373 //! X position of caret in world coordinate in line 00374 double m_XcaretinLine; 00375 00376 //! Y position of caret in world coordinate in line 00377 double m_YcaretinLine; 00378 00379 //! Untransformed bounding box. 00380 mutable a2dBoundingBox m_untransbbox; 00381 00382 //! Untransformed bounding box changed 00383 mutable bool m_utbbox_changed; 00384 00385 //! Selection starting position 00386 size_t m_selection_start_pos; 00387 //! Selection end position 00388 size_t m_selection_end_pos; 00389 00390 //! The first editable character, usually 0, but may be different for a2dVisibleProperty 00391 size_t m_firsteditable; 00392 00393 //! Alignment. 00394 int m_alignment; 00395 00396 private: 00397 //!this is a not implemented copy constructor that avoids automatic creation of one 00398 a2dText( const a2dText &other ); 00399 }; 00400 00401 #if defined(WXART2D_USINGDLL) 00402 template class A2DCANVASDLLEXP a2dSmrtPtr<a2dText>; 00403 #endif 00404 00405 #endif /* __WXCANTEXT_H__ */