1 /*
2    Copyright (c) by Valery Goryachev (Wal)
3 */
4 
5 #pragma once
6 
7 namespace wal
8 {
9 	extern int uiClassButton;
10 	extern int uiClassEditLine;
11 	extern int uiClassMenuBar;
12 	extern int uiClassPopupMenu;
13 	extern int uiClassSButton;
14 	extern int uiClassScrollBar;
15 	extern int uiClassTextList;
16 	extern int uiClassVListWin;
17 	extern int uiClassStatic;
18 	extern int uiClassToolTip;
19 
20 	enum BASE_COMMANDS
21 	{
22 		_CMD_BASE_BEGIN_POINT_ = -99,
23 		CMD_ITEM_CLICK,      //может случаться в объектах с подэлементами при нажатии enter или doubleclick (например VList)
24 		CMD_ITEM_CHANGED,
25 		CMD_SBUTTON_INFO, //with subcommands
26 		CMD_SCROLL_INFO,     //with subcommands
27 		CMD_MENU_INFO,    //with subcommands
28 		CMD_EDITLINE_INFO //with subcommands
29 	};
30 
31 	void BaseInit();
32 	void Draw3DButtonW2( GC& gc, crect r, unsigned bg, bool up );
33 
34 	extern unicode_t ABCString[];
35 	extern int ABCStringLen;
36 
37 	// Menu text that is split to 3 parts by hot key.
38 	// The hot key character is prepended by '&', like in Windows menu
39 	class MenuTextInfo
40 	{
41 		unicode_t* strBeforeHk;
42 		unicode_t* strHk;
43 		unicode_t* strAfterHk;
44 		unicode_t* strFull; // required to calculate text extents quickly
45 		unicode_t* strRaw; // return const value for editing. Update the value with SetText()
46 		unicode_t hotkeyUpperCase;
47 		void ParseHkText( const unicode_t* inStr );
48 		void Clear();
49 		void Init( const MenuTextInfo& src );
50 	public:
51 		explicit MenuTextInfo( const unicode_t* inStr );
MenuTextInfo()52 		MenuTextInfo() : strBeforeHk( 0 ), strHk( 0 ), strAfterHk( 0 ), strFull( 0 ), strRaw ( 0 ), hotkeyUpperCase( 0 ) {}
MenuTextInfo(const MenuTextInfo & src)53 		MenuTextInfo( const MenuTextInfo& src ) { Init( src ); }
54 		MenuTextInfo& operator=( const MenuTextInfo& src ) { Clear(); Init( src ); return *this; };
~MenuTextInfo()55 		~MenuTextInfo() { Clear(); }
56 
57 		void SetText( const unicode_t* inStr );
GetRawText()58 		const unicode_t* GetRawText() const { return strRaw; }
59 		void DrawItem( GC& gc, int x, int y, int color_text, int color_hotkey ) const;
60 		void DrawItem( GC& gc, int x, int y, int color_text, int color_hotkey, bool antialias ) const;
61 		cpoint GetTextExtents( GC& gc, cfont* font = 0 ) const
62 		{
63 			if ( strFull == 0 ) { return cpoint( 0, 0 ); }
64 
65 			if ( font ) { gc.Set( font ); }
66 
67 			return gc.GetTextExtents( strFull );
68 		}
isEmpty()69 		int isEmpty() const { return strFull == 0; }
isHotkeyMatching(unicode_t charUpperCase)70 		bool isHotkeyMatching( unicode_t charUpperCase ) const { return hotkeyUpperCase != 0 && charUpperCase == hotkeyUpperCase; }
71 	};
72 
73 	class Button: public Win
74 	{
75 	private:
76 		bool         m_Pressed;
77 		MenuTextInfo m_Text;
78 		clPtr<cicon> m_Icon;
79 		int          m_CommandId;
80 		bool         m_ShowIcon;
81 
HasIcon()82 		bool HasIcon() const { return m_Icon.ptr() && m_ShowIcon; }
SendCommand()83 		void SendCommand() { Command( m_CommandId, 0, this, 0 ); }
84 	public:
85 		Button( int nId, Win* parent, const unicode_t* txt,  int id, crect* rect = 0, int iconX = 16, int iconY = 16 );
86 		void Set( const unicode_t* txt, int id, int iconX = 16, int iconY = 16 );
CommandId()87 		int CommandId() const { return m_CommandId; }
88 		virtual void Paint( GC& gc, const crect& paintRect );
89 		virtual bool EventFocus( bool recv );
90 		virtual bool EventMouse( cevent_mouse* pEvent );
91 		virtual bool EventKey( cevent_key* pEvent );
92 		virtual Win* IsHisHotKey( cevent_key* pEvent );
93 		virtual void OnChangeStyles();
SetShowIcon(bool Show)94 		virtual void SetShowIcon( bool Show ) { m_ShowIcon = Show; }
95 		virtual int UiGetClassId();
96 		virtual ~Button();
97 	};
98 
99 	enum SButtonInfo
100 	{
101 		// subcommands of CMD_SBUTTON_INFO
102 		SCMD_SBUTTON_CHECKED = 1,
103 		SCMD_SBUTTON_CLEARED = 0
104 	};
105 
106 //Checkbox and Radiobutton
107 	class SButton: public Win
108 	{
109 		bool isSet;
110 		//std::vector<unicode_t> text;
111 		MenuTextInfo text;
112 		int group;
113 	public:
114 		SButton( int nId, Win* parent, unicode_t* txt, int _group, bool _isSet = false, crect* rect = 0 );
115 
IsSet()116 		bool IsSet() const { return isSet; }
117 		void Change( bool _isSet );
118 		virtual void Paint( GC& gc, const crect& paintRect );
119 		virtual bool EventMouse( cevent_mouse* pEvent );
120 		virtual bool EventKey( cevent_key* pEvent );
121 		virtual Win* IsHisHotKey( cevent_key* pEvent );
122 		virtual bool EventFocus( bool recv );
123 		virtual bool Broadcast( int id, int subId, Win* win, void* data );
124 		virtual int UiGetClassId();
125 		virtual ~SButton();
126 	};
127 
128 
129 	class EditBuf
130 	{
131 		std::vector<unicode_t> data;
132 		int size;   //размер буфера
133 		int count;  //количесво символов в строке
134 		int cursor; //позиция курсора
135 		int marker; //точка, от которой до курсора - выделенный блок
136 
137 		enum { STEP = 0x100 };
138 		void SetSize( int n );
139 		void InsertBlock( int pos, int n );
140 		void DeleteBlock( int pos, int n );
141 
142 	public:
143 
144 		void Begin  ( bool mark = false )  { cursor = 0; if ( !mark ) { marker = cursor; } }
145 		void End ( bool mark = false )  { cursor = count; if ( !mark ) { marker = cursor; } }
146 		void Left   ( bool mark = false )  { if ( cursor > 0 ) { cursor--; } if ( !mark ) { marker = cursor; } }
147 		void Right  ( bool mark = false )  { if ( cursor < count ) { cursor++; } if ( !mark ) { marker = cursor; } }
148 
149 		void CtrlLeft  ( bool mark = false );
150 		void CtrlRight ( bool mark = false );
151 
152 		void SetCursor ( int n, bool mark = false ) { if ( n > count ) { n = count - 1; } if ( n < 0 ) { n = 0; } cursor = n; if ( !mark ) { marker = cursor; }}
Unmark()153 		void Unmark ()       { marker = cursor; }
154 
Marked()155 		bool Marked() const { return cursor != marker; }
156 		bool DelMarked();
Marked(int n)157 		bool Marked( int n ) const
158 		{
159 			return cursor != marker &&
160 			       ( ( cursor < marker && n >= cursor && n < marker ) || ( cursor > marker && n < cursor && n >= marker ) );
161 		}
162 
163 		void Insert( unicode_t t );
164 		void Insert( const unicode_t* txt );
165 		void Del( bool DelteWord );
166 		void Backspace( bool DeleteWord );
167 		void Set( const unicode_t* s, bool mark = false );
168 
Ptr()169 		const unicode_t* Ptr() const { return data.data(); }
Ptr()170 		unicode_t* Ptr() { return data.data(); }
171 		unicode_t operator []( int n ) { return data[n]; }
172 
Count()173 		int   Count()  const { return count; }
Cursor()174 		int   Cursor() const { return cursor; }
Marker()175 		int   Marker() const { return marker; }
176 
Clear()177 		void  Clear() { marker = cursor = count = 0; }
178 
GetText()179 		const std::vector<unicode_t>& GetText() const { return data; }
SetText(const std::vector<unicode_t> & t)180 		void SetText( const std::vector<unicode_t>& t ) { Set( t.data(), false ); }
181 
EditBuf(const unicode_t * s)182 		EditBuf( const unicode_t* s ): size( 0 ), count( 0 ) { Set( s );}
EditBuf()183 		EditBuf(): size( 0 ), count( 0 ), cursor( 0 ), marker( 0 ) {}
184 
185 		static int GetCharGroup( unicode_t c ); //for word left/right (0 - space)
186 	};
187 
188 	enum EditLineCmd
189 	{
190 		// subcommands of CMD_EDITLINE_INFO
191 		SCMD_EDITLINE_CHANGED = 100,
192 		SCMD_EDITLINE_DELETED,
193 		SCMD_EDITLINE_INSERTED
194 	};
195 
196 	class clValidator: public iIntrusiveCounter
197 	{
198 	public:
~clValidator()199 		virtual ~clValidator() {};
200 		virtual bool IsValid( const std::vector<unicode_t>& Str ) const = 0;
201 	};
202 
203 	class clUnsignedInt64Validator: public clValidator
204 	{
205 	public:
206 		virtual bool IsValid( const std::vector<unicode_t>& Str ) const override;
207 	};
208 
209 	/// validate date in format dd.mm.yyyy
210 	class clDateValidator: public clValidator
211 	{
212 	public:
213 		virtual bool IsValid( const std::vector<unicode_t>& Str ) const override;
214 	};
215 
216 	/// validate time in format HH:MM:SS,MSEC
217 	class clTimeValidator: public clValidator
218 	{
219 	public:
220 		virtual bool IsValid( const std::vector<unicode_t>& Str ) const override;
221 	};
222 
223 	class EditLine: public Win
224 	{
225 	public:
226 		enum FLAGS
227 		{
228 			USEPARENTFOCUS = 1,
229 			READONLY = 2
230 		};
231 
232 	private:
233 		bool _use_alt_symbols;
234 		unsigned _flags;
UseParentFocus()235 		bool UseParentFocus() const { return (_flags & USEPARENTFOCUS) != 0; }
236 		EditBuf text;
237 		int _chars;
238 		bool cursorVisible;
239 		bool passwordMode;
240 		bool showSpaces;
241 		// quick search line accepts alt keys. Edit controls do not: alt is used for hotkeys in dialogs
242 		bool doAcceptAltKeys;
243 		int first;
244 		bool frame3d;
245 		int charH;
246 		int charW;
247 		bool m_ReplaceMode;
248 
249 		clPtr<clValidator> m_Validator;
250 
251 		CaptureSD captureSD;
252 
253 		void DrawCursor( GC& gc );
254 		bool CheckCursorPos(); //true - if redrawing is needed
255 		void ClipboardCopy();
256 		void ClipboardPaste();
257 		void ClipboardCut();
258 		int GetCharPos( cpoint p );
259 	protected:
Changed()260 		virtual void Changed() { if ( Parent() ) { Parent()->Command( CMD_EDITLINE_INFO, SCMD_EDITLINE_CHANGED, this, 0 ); } }
SendCommand(const int cmd)261 		virtual void SendCommand(const int cmd)
262 		{
263 			if ( Parent() )
264 			{
265 				Parent()->Command( CMD_EDITLINE_INFO, cmd, this, 0 );
266 			}
267 		}
268 	public:
269 		EditLine( int nId, Win* parent, const crect* rect, const unicode_t* txt, int chars = 10, bool frame = true, unsigned flags = 0 );
SetAcceptAltKeys()270 		void SetAcceptAltKeys() { doAcceptAltKeys = true; }
271 		virtual void Paint( GC& gc, const crect& paintRect );
272 		virtual bool EventMouse( cevent_mouse* pEvent );
273 		virtual bool EventKey( cevent_key* pEvent );
274 		virtual void EventTimer( int tid );
275 		virtual bool EventFocus( bool recv );
276 		virtual void EventSize( cevent_size* pEvent );
277 		virtual bool InFocus() override;
278 		virtual void SetFocus() override;
279 		void Clear();
280 		void SetText( const unicode_t* txt, bool mark = false );
281 		void SetText( const std::string& utf8txt, bool mark = false );
282 		void Insert( unicode_t t );
283 		void Insert( const unicode_t* txt );
IsEmpty()284 		bool IsEmpty() const { return text.Count() == 0; }
IsReadOnly()285 		bool IsReadOnly() const { return (_flags & READONLY) != 0; }
GetCursorPos()286 		int GetCursorPos() { return text.Cursor(); }
GetMarkerPos()287 		int GetMarkerPos() { return text.Marker(); }
288 		void SetCursorPos( int c, bool mark = false ) { text.SetCursor( c, mark ); }
SetReplaceMode(bool ReplaceMode)289 		void SetReplaceMode( bool ReplaceMode ) { m_ReplaceMode = ReplaceMode; }
290 		std::vector<unicode_t> GetText() const;
291 		std::string GetTextStr() const;
292 		void SetPasswordMode( bool enable = true ) { passwordMode = enable; Invalidate(); }
293 		void SetShowSpaces( bool enable = true ) { showSpaces = enable; Invalidate(); }
294 		virtual int UiGetClassId();
295 		virtual void OnChangeStyles();
EnableAltSymbols(bool e)296 		void EnableAltSymbols( bool e ) { _use_alt_symbols = e; }
297 		virtual ~EditLine();
SetValidator(clPtr<clValidator> Validator)298 		void SetValidator( clPtr<clValidator> Validator ) { m_Validator = Validator; }
299 	};
300 
301 	extern cpoint GetStaticTextExtent( GC& gc, const unicode_t* s, cfont* font );
302 
303 	class StaticLine: public Win
304 	{
305 	public:
306 		enum ALIGN
307 		{
308 			LEFT = -1,
309 			CENTER = 0,
310 			RIGHT = 1
311 		};
312 		//MenuTextInfo text;
313 		std::vector<unicode_t> text;
314 		ALIGN align;
315 		int width; //ширина в ВЫСОТАХ фонта
316 	public:
317 		StaticLine( int nId, Win* parent, const unicode_t* txt, crect* rect = nullptr, ALIGN al = LEFT, int w = -1 );
318 		virtual void Paint( GC& gc, const crect& paintRect );
319 		//void SetText( const unicode_t* txt ) { text.SetText(txt) ; Invalidate(); }
320 		void SetTextUtf8( const std::string& txt );
321 		void SetText( const unicode_t* txt );
322 		virtual int UiGetClassId();
323 	};
324 
325 	// single line label that may have '&' in the text to designate hotkey
326 	// Has master dialog control, which is returned by IsHisHotKey on matching hotkey
327 	class StaticLabel : public Win
328 	{
329 		MenuTextInfo text;
330 		Win* master;
331 	public:
332 		StaticLabel( int nId, Win* parent, const unicode_t* txt, Win* _master = 0, crect* rect = 0 );
333 		virtual void Paint( GC& gc, const crect& paintRect );
334 		virtual Win* IsHisHotKey( cevent_key* pEvent );
335 		virtual int UiGetClassId();
336 	};
337 
338 
339 	enum ScrollCmd
340 	{
341 		//subcommands of CMD_SCROLL_INFO
342 		SCMD_SCROLL_VCHANGE = 1,
343 		SCMD_SCROLL_HCHANGE,
344 
345 		SCMD_SCROLL_LINE_UP,
346 		SCMD_SCROLL_LINE_DOWN,
347 		SCMD_SCROLL_LINE_LEFT,
348 		SCMD_SCROLL_LINE_RIGHT,
349 		SCMD_SCROLL_PAGE_UP,
350 		SCMD_SCROLL_PAGE_DOWN,
351 		SCMD_SCROLL_PAGE_LEFT,
352 		SCMD_SCROLL_PAGE_RIGHT,
353 		SCMD_SCROLL_TRACK
354 	};
355 
356 	struct ScrollInfo
357 	{
358 		seek_t m_Size;
359 		seek_t m_PageSize;
360 		seek_t m_Pos;
361 		bool   m_AlwaysHidden;
ScrollInfoScrollInfo362 		ScrollInfo()
363 			: m_Size( 0 )
364 			, m_PageSize( 0 )
365 			, m_Pos( 0 )
366 			, m_AlwaysHidden( false )
367 		{}
ScrollInfoScrollInfo368 		ScrollInfo( seek_t _size, seek_t _pageSize, seek_t _pos )
369 			: m_Size( _size )
370 			, m_PageSize( _pageSize )
371 			, m_Pos( _pos )
372 			, m_AlwaysHidden( false )
373 		{}
374 		bool operator==( const ScrollInfo& o )
375 		{
376 			return m_Size == o.m_Size && m_PageSize == o.m_PageSize && m_Pos == o.m_Pos && m_AlwaysHidden == o.m_AlwaysHidden;
377 		}
378 	};
379 
380 	class ScrollBar: public Win
381 	{
382 		bool vertical;
383 		ScrollInfo si;
384 
385 		int len; //расстояние между крайними кнопками
386 		int bsize; // размер средней кнопки
387 		int bpos; // расстояние от средней кнопки до первой
388 
389 		crect b1Rect, b2Rect, b3Rect;
390 
391 		bool trace; // состояние трассировки
392 		int traceBPoint; // точка нажатия мыши от начала средней кнопки (испю при трассировке)
393 
394 		bool autoHide;
395 
396 		bool b1Pressed;
397 		bool b2Pressed;
398 
399 		Win* managedWin;
400 
401 		CaptureSD captureSD;
402 
403 		void Recalc( cpoint* newSize = 0 );
404 		void SendManagedCmd( int subId, void* data );
405 	public:
406 		ScrollBar( int nId, Win* parent, bool _vertical, bool _autoHide = true,  crect* rect = 0 );
407 		void SetScrollInfo( ScrollInfo* s );
408 		void SetManagedWin( Win* w = 0 ) { managedWin = w; SetScrollInfo( 0 ); }
409 		virtual void Paint( GC& gc, const crect& paintRect );
410 		virtual bool Command( int id, int subId, Win* win, void* data );
411 		virtual bool EventMouse( cevent_mouse* pEvent );
412 		virtual void EventTimer( int tid );
413 		virtual void EventSize( cevent_size* pEvent );
414 		virtual int UiGetClassId();
415 		virtual ~ScrollBar();
416 	};
417 
418 
419 	class VListWin: public Win
420 	{
421 	public:
422 		enum SelectType { NO_SELECT = 0, SINGLE_SELECT, MULTIPLE_SELECT };
423 		enum BorderType { NO_BORDER = 0, SINGLE_BORDER, BORDER_3D};
424 	private:
425 		SelectType selectType;
426 		BorderType borderType;
427 
428 		int itemHeight;
429 		int itemWidth;
430 
431 		int xOffset;
432 		int count;
433 		int first;
434 		int current;
435 		int pageSize;
436 		int captureDelta;
437 
438 		unsigned borderColor; //used only for SINGLE_BORDER
439 		unsigned bgColor; //for 3d border and scroll block
440 
441 		CaptureSD captureSD;
442 
443 		ScrollBar vScroll;
444 		ScrollBar hScroll;
445 
446 		Layout layout;
447 
448 		crect listRect; //rect в котором надо рисовать список
449 		crect scrollRect;
450 
451 		IntList selectList;
452 
453 	protected:
454 		void SetCount( int );
455 		void SetItemSize( int h, int w );
456 		void CalcScroll();
457 //	void SetBlockLSize(int);
458 //	void SetBorderColor(unsigned);
459 
GetCount()460 		int GetCount() { return count; }
GetItemHeight()461 		int GetItemHeight() { return itemHeight; }
GetItemWidth()462 		int GetItemWidth() { return itemWidth; }
463 
464 		void SetCurrent( int );
465 	public:
466 		VListWin( WTYPE t, unsigned hints, int nId, Win* _parent, SelectType st, BorderType bt, crect* rect );
467 		virtual void DrawItem( GC& gc, int n, crect rect );
468 
469 		void MoveCurrent( int n, bool mustVisible = true );
470 		void MoveFirst( int n );
471 		void MoveXOffset( int n );
472 		void SetNoCurrent();
473 
GetCurrent()474 		int GetCurrent() const { return current; }
GetPageFirstItem()475 		int GetPageFirstItem() const { return first; }
GetPageItemCount()476 		int GetPageItemCount() const { return pageSize; }
477 
478 
479 		void ClearSelection();
480 		void ClearSelected( int n1, int n2 );
481 		void SetSelected( int n1, int n2 );
482 		bool IsSelected( int );
483 
484 		virtual void Paint( GC& gc, const crect& paintRect );
485 		virtual void EventSize( cevent_size* pEvent );
486 		virtual bool EventKey( cevent_key* pEvent );
487 		virtual bool EventMouse( cevent_mouse* pEvent );
488 		virtual bool EventFocus( bool recv );
489 		virtual bool Command( int id, int subId, Win* win, void* data );
490 		virtual void EventTimer( int tid );
491 		virtual int UiGetClassId();
492 	};
493 
494 
495 	struct TLNode
496 	{
497 		int pixelWidth;
498 		std::vector<unicode_t> str;
499 		long intData;
500 		void* ptrData;
TLNodeTLNode501 		TLNode() : pixelWidth( -1 ), intData( 0 ), ptrData( 0 ) {}
502 		TLNode( const unicode_t* s, int i = 0, void* p = 0 ) : pixelWidth( -1 ), str( new_unicode_str( s ) ), intData( i ), ptrData( p ) {}
503 	};
504 
505 	class TextList: public VListWin
506 	{
507 		std::vector<TLNode> list;
508 		bool valid;
509 		int fontH;
510 		int fontW;
511 	public:
512 		TextList( WTYPE t, unsigned hints, int nId, Win* _parent, SelectType st, BorderType bt, crect* rect );
513 		virtual void DrawItem( GC& gc, int n, crect rect );
514 		void Clear();
515 		void Append( const unicode_t* txt, int i = 0, void* p = 0 );
516 		void DataRefresh();
517 
GetCurrentString()518 		const unicode_t* GetCurrentString() { int cnt = list.size(), c = GetCurrent(); return c < 0 || c >= cnt ? 0 : list[ c ].str.data(); }
GetCurrentPtr()519 		void* GetCurrentPtr() { int cnt = list.size(), c = GetCurrent(); return c < 0 || c >= cnt ? 0 : list[ c ].ptrData; }
GetCurrentInt()520 		int GetCurrentInt() { int cnt = list.size(), c = GetCurrent(); return c < 0 || c >= cnt ? -1 : list[ c ].intData; }
521 
522 		void SetHeightRange( LSRange range ); //in characters
523 		void SetWidthRange( LSRange range ); //in characters
524 		virtual int UiGetClassId();
525 		virtual ~TextList();
526 	};
527 
528 
529 
530 	enum CmdMenuInfo
531 	{
532 		//subcommands of CMD_MENU_INFO
533 		SCMD_MENU_CANCEL = 0,
534 		SCMD_MENU_SELECT = 1
535 	};
536 
537 	class PopupMenu;
538 
539 	class MenuData: public iIntrusiveCounter
540 	{
541 	public:
542 		enum TYPE { CMD = 1, SPLIT,   SUB   };
543 
544 		struct Node
545 		{
546 			int type;
547 			int id;
548 			//std::vector<unicode_t> leftText;
549 			MenuTextInfo leftText;
550 
551 			std::vector<unicode_t> rightText;
552 			MenuData* sub;
553 			//Node(): type( 0 ), sub( 0 ) {}
NodeNode554 			Node( int _type, int _id, const unicode_t* s,  const unicode_t* rt, MenuData* _sub )
555 				: type( _type ), id( _id ), leftText( s ), sub( _sub )
556 			{
557 				//if ( s ) { leftText = new_unicode_str( s ); }
558 
559 				if ( rt ) { rightText = new_unicode_str( rt ); }
560 			}
561 		};
562 
563 	private:
564 		friend class PopupMenu;
565 
566 		wal::ccollect<Node> list;
567 	public:
568 		MenuData();
Count()569 		int Count() { return list.count(); }
570 		void AddCmd( int id, const unicode_t* s, const unicode_t* rt = 0 ) { Node node( CMD, id, s, rt, 0 ); list.append( node ); }
571 		void AddCmd( int id, const char* s, const char* rt = 0 ) { AddCmd( id, utf8_to_unicode( s ).data(), rt ? utf8_to_unicode( rt ).data() : 0 ); }
AddSplit()572 		void AddSplit() { Node node( SPLIT, 0, 0, 0, 0 ); list.append( node ); }
AddSub(const unicode_t * s,MenuData * data)573 		void AddSub( const unicode_t* s, MenuData* data ) { Node node( SUB, 0, s, 0, data ); list.append( node ); }
AddSub(const char * s,MenuData * data)574 		void AddSub( const char* s, MenuData* data ) { AddSub( utf8_to_unicode( s ).data(), data ); }
~MenuData()575 		~MenuData() {}
576 	};
577 
578 	class PopupMenu: public Win
579 	{
580 		struct Node
581 		{
582 			MenuData::Node* data;
583 			crect rect;
584 			bool enabled;
585 		};
586 		wal::ccollect<Node> list;
587 		int selected;
588 		clPtr<PopupMenu> sub;
589 		bool SetSelected( int n );
590 		bool OpenSubmenu();
591 		Win* cmdOwner;
592 
593 		bool IsCmd( int n );
594 		bool IsSplit( int n );
595 		bool IsSub( int n );
596 		bool IsEnabled( int n );
597 
598 		int fontHeight;
599 		int leftWidth;
600 		int rightWidth;
601 
602 		void DrawItem( GC& gc, int n );
603 	public:
604 		PopupMenu( int nId, Win* parent, MenuData* d, int x, int y, Win* _cmdOwner = 0 );
605 		virtual bool EventMouse( cevent_mouse* pEvent ) override;
606 		virtual bool EventKey( cevent_key* pEvent ) override;
607 		virtual void Paint( GC& gc, const crect& paintRect ) override;
608 		virtual bool Command( int id, int subId, Win* win, void* data ) override;
609 		virtual int UiGetClassId() override;
610 		virtual ~PopupMenu();
611 	};
612 
613 	int DoPopupMenu( int nId, Win* parent, MenuData* d, int x, int y );
614 
615 	class MenuBar: public Win
616 	{
617 		struct Node
618 		{
619 			//std::vector<unicode_t> text;
620 			MenuTextInfo text;
621 			MenuData* data;
NodeNode622 			Node( MenuTextInfo _text, MenuData* _data ) : text( _text ), data( _data ) {}
623 		};
624 
625 		wal::ccollect<Node> list;
626 		wal::ccollect<crect> rectList;
627 		int select;
628 		int lastMouseSelect;
629 		clPtr<PopupMenu> sub;
630 
631 		crect ItemRect( int n );
InvalidateRectList()632 		void InvalidateRectList() { rectList.clear(); }
633 		void DrawItem( GC& gc, int n );
634 		void SetSelect( int n );
635 		void OpenSub();
Left()636 		void Left() { SetSelect( select <= 0 ? ( list.count() - 1 ) : ( select - 1 ) ); }
Right()637 		void Right() { SetSelect( select == list.count() - 1  ? 0 : select + 1 ); }
638 		int GetPointItem( cpoint p );
639 	public:
640 		MenuBar( int nId, Win* parent, crect* rect = 0 );
641 		void Paint( GC& gc, const crect& paintRect );
642 		virtual bool EventMouse( cevent_mouse* pEvent );
643 		virtual bool EventKey( cevent_key* pEvent );
644 		virtual bool Command( int id, int subId, Win* win, void* d );
645 		virtual bool EventFocus( bool recv );
646 		virtual void EventEnterLeave( cevent* pEvent );
647 		virtual void EventSize( cevent_size* pEvent );
648 		virtual int UiGetClassId();
649 		virtual int GetSelect() const;
650 		virtual void OnChangeStyles();
651 
Clear()652 		void Clear() { list.clear(); InvalidateRectList(); }
653 		void Add( MenuData* data, const unicode_t* text );
654 		virtual ~MenuBar();
655 	};
656 
657 ////////////////////////// ComboBox
658 
659 	class ComboBox: public Win
660 	{
661 	public:
662 		enum FLAGS
663 		{
664 			MODE_UP  = 1,
665 			READONLY = 2
666 		};
667 
668     private:
669 		unsigned _flags;
670 		CaptureSD captureSD;
671 		Layout _lo;
672 
673         struct Node
674 		{
675 			std::vector<unicode_t> text;
676 			void* data;
677 		};
678 
679         EditLine _edit;
680 		crect _buttonRect;
681 		ccollect<Node, 0x100> _list;
682         clPtr<TextList> _box;
683 //		int _cols;
684 		int _rows;
685 		int _current;
686 
687 	protected:
688 		void OpenBox();
689 		void RefreshBox();
690 
IsEditLine(Win * w)691 		bool IsEditLine( Win* w ) const { return w == &_edit; }
692 
693 	public:
694 		ComboBox( int nId, Win* parent, int cols, int rows, unsigned flags = 0,  crect* rect = 0 );
~ComboBox()695         virtual ~ComboBox() {}
696 
697         virtual void Paint( GC& gc, const crect& paintRect );
698 		virtual bool EventMouse( cevent_mouse* pEvent );
699         virtual bool EventKey( cevent_key* pEvent );
700 		virtual bool EventFocus( bool recv );
701 		virtual bool Command( int id, int subId, Win* win, void* d );
702 		virtual void OnChangeStyles();
703 		virtual int UiGetClassId();
704 
705         void Clear();
706 		void Append( const unicode_t* text, void* data = 0 );
707 		void Append( const char* text, void* data = 0 );
708 
709 		std::vector<unicode_t> GetText() const;
710 		std::string GetTextStr() const;
711 		void SetText( const unicode_t* txt, bool mark = false );
712 		void SetText( const std::string& utf8txt, bool mark = false );
713 		void InsertText( unicode_t t );
714 		void InsertText( const unicode_t* txt );
GetCursorPos()715 		int GetCursorPos() { return _edit.GetCursorPos(); }
GetMarkerPos()716 		int GetMarkerPos() { return _edit.GetMarkerPos(); }
717 		void SetCursorPos( int c, bool mark = false ) { _edit.SetCursorPos( c, mark ); }
718 
IsReadOnly()719 		bool IsReadOnly() const { return (_flags & ComboBox::READONLY) != 0; }
Count()720 		int Count() const { return _list.count(); }
Current()721 		int Current() const { return _current; }
722 		const unicode_t* ItemText( int n );
723 
724 		void* ItemData( int n );
725 		void MoveCurrent( int n, bool notify = true );
IsBoxOpened()726 		bool IsBoxOpened() { return _box.ptr() != 0; }
727 		void CloseBox();
728 
729         virtual bool OnOpenBox();
730 		virtual void OnCloseBox();
731 		virtual void OnItemChanged( int ItemIndex );
732 	};
733 
734 //ToolTip is global, setting new one is replaceing previous
735 	void ToolTipShow( Win* w, int x, int y, const unicode_t* s );
736 	void ToolTipShow( int x, int y, const char* s );
737 	void ToolTipHide();
738 
739 
740 }// namespace wal
741