1 /*
2 * Part of WCM Commander
3 * https://github.com/corporateshark/WCMCommander
4 * wcm@linderdaum.com
5 */
6
7 #include "globals.h"
8 #include "nc.h"
9 #include "ncfonts.h"
10 #include "ncdialogs.h"
11 #include "wcm-config.h"
12 #include "string-util.h"
13 #include "ltext.h"
14 #include "unicode_lc.h"
15 #include "panel.h"
16 #include "nceditline.h"
17
18 bool createDialogAsChild //= false;
19 = true;
20
NCShadowWin(Win * parent)21 NCShadowWin::NCShadowWin( Win* parent )
22 : Win( Win::WT_CHILD, 0, parent ) //, &crect(0,0,300,100))
23 {
24
25 }
26
27
Paint(wal::GC & gc,const crect & paintRect)28 void NCShadowWin::Paint( wal::GC& gc, const crect& paintRect )
29 {
30 crect cr = ClientRect();
31 gc.SetFillColor( 0 ); //::g_WcmConfig.whiteStyle ? 0x404040 : 0x01);
32 gc.FillRect( cr );
33 }
34
~NCShadowWin()35 NCShadowWin::~NCShadowWin() {}
36
37
CloseDialog(int cmd)38 void NCDialog::CloseDialog( int cmd )
39 {
40 EndModal( cmd );
41 }
42
OnCancel()43 void NCDialog::OnCancel()
44 {
45 CloseDialog( CMD_CANCEL );
46 }
47
48
GetChildFont(Win * w,int fontId)49 cfont* NCDialog::GetChildFont( Win* w, int fontId )
50 {
51 return g_DialogFont.ptr();
52 }
53
Command(int id,int subId,Win * win,void * data)54 bool NCDialog::Command( int id, int subId, Win* win, void* data )
55 {
56 if ( id && win && win->UiGetClassId() == uiClassButton )
57 {
58 if ( id == CMD_CANCEL )
59 {
60 OnCancel();
61 }
62 else
63 {
64 CloseDialog( id );
65 }
66
67 return true;
68 }
69
70 return false;
71 }
72
73 int uiClassNCDialog = GetUiID( "NCDialog" );
74
UiGetClassId()75 int NCDialog::UiGetClassId()
76 {
77 return m_nId;
78 // return uiClassNCDialog;
79 }
80
NCDialog(bool asChild,int nId,NCDialogParent * parent,const unicode_t * headerText,ButtonDataNode * blist)81 NCDialog::NCDialog( bool asChild, int nId, NCDialogParent* parent, const unicode_t* headerText, ButtonDataNode* blist ) //, unsigned bcolor, unsigned fcolor)
82 : OperThreadWin( asChild ? Win::WT_CHILD : WT_MAIN /*WT_POPUP*/, 0, nId, parent ), //, &crect(0,0,300,100)),
83 _shadow( parent ),
84 // _fcolor(fcolor),
85 // _bcolor(bcolor),
86 _header( nId, this, headerText ),
87 _lo( 9, 9 ),
88 _buttonLo( 3, 16 ),
89 _headerLo( 3, 3 ),
90 _parentLo( 3, 3 ),
91 enterCmd( 0 ),
92 m_nId( nId )
93 {
94 Enable();
95
96 _lo.SetLineGrowth( 4 );
97 _lo.SetColGrowth( 4 );
98
99
100 _lo.ColSet( 0, 2 );
101 _lo.ColSet( 1, 10 );
102 _lo.ColSet( 2, 3 );
103
104 _lo.ColSet( 3, 5 );
105 _lo.ColSet( 5, 5 );
106
107 _lo.ColSet( 6, 3 );
108 _lo.ColSet( 7, 10 );
109 _lo.ColSet( 8, 2 );
110
111 _lo.LineSet( 0, 2 );
112 _lo.LineSet( 1, 10 );
113 _lo.LineSet( 2, 3 );
114
115 _lo.LineSet( 3, 3 );
116 //_lo.LineSet(5, 5);
117
118 _lo.LineSet( 6, 3 );
119 _lo.LineSet( 7, 5 );
120 _lo.LineSet( 8, 2 );
121
122 _lo.ColSet( 4, 16, 100000 );
123 _lo.LineSet( 4, 16, 100000 );
124
125 _lo.AddRect( &_borderRect, 0, 0, 8, 8 );
126 _lo.AddRect( &_frameRect, 2, 2, 6, 6 );
127
128 _headerLo.ColSet( 0, 1, 1000 );
129 _headerLo.ColSet( 2, 1, 1000 );
130 _headerLo.LineSet( 0, 2 );
131 _headerLo.LineSet( 2, 2 );
132 _headerLo.AddWin( &_header, 1, 1 );
133 _lo.AddLayout( &_headerLo, 1, 4 );
134
135 _buttonLo.ColSet( 0, 10, 1000 );
136 _buttonLo.ColSet( 15, 10, 1000 );
137 _buttonLo.LineSet( 0, 2 );
138 _buttonLo.LineSet( 2, 2 );
139
140 _parentLo.ColSet( 0, 20, 1000 );
141 _parentLo.ColSet( 2, 20, 1000 );
142 _parentLo.LineSet( 0, 20, 1000 );
143 _parentLo.LineSet( 2, 20, 1000 );
144 _parentLo.AddWin( this, 1, 1 );
145
146 _parentLo.SetLineGrowth( 0 );
147 _parentLo.SetLineGrowth( 2 );
148
149 _parentLo.SetColGrowth( 0 );
150 _parentLo.SetColGrowth( 2 );
151
152 if ( blist )
153 {
154 int n = 0;
155 int minW = 0;
156
157 for ( ; blist->utf8text && n < 7; blist++, n++ )
158 {
159
160 clPtr<Button> p = new Button( 0, this, utf8_to_unicode( _LT( carray_cat<char>( "DB>", blist->utf8text ).data(), blist->utf8text ) ).data(), blist->cmd );
161
162 p->Show();
163 p->Enable();
164
165 if ( n > 0 )
166 {
167 _buttonLo.ColSet( n * 2, 5 );
168 }
169
170 _buttonLo.AddWin( p.ptr(), 1, n * 2 + 1 );
171
172 if ( minW < p->GetLSize().x.minimal )
173 {
174 minW = p->GetLSize().x.minimal;
175 }
176
177 _bList.append( p );
178 //break; ???
179
180 }
181
182 if ( minW > 0 )
183 for ( int i = 0; i < _bList.count(); i++ )
184 {
185 LSize s = _bList[i]->GetLSize();
186 s.x.minimal = s.x.maximal = minW;
187 _bList[i]->SetLSize( s );
188 };
189
190 if ( _bList.count() )
191 {
192 _bList[0]->SetFocus();
193 }
194
195 }
196
197 _lo.AddLayout( &_buttonLo, 5, 4 );
198
199 _header.Enable();
200 _header.Show();
201
202 SetLayout( &_lo );
203
204 if ( Type() == WT_CHILD && parent )
205 {
206 parent->AddLayout( &_parentLo );
207 }
208
209
210 SetPosition();
211
212 SetName( appName );
213 }
214
GetDownButton()215 Win* NCDialog::GetDownButton()
216 {
217 return _bList.count() > 0 ? _bList[0].ptr() : 0;
218 }
219
220
MaximizeIfChild(bool x,bool y)221 void NCDialog::MaximizeIfChild( bool x, bool y )
222 {
223 if ( Type() == WT_CHILD && Parent() )
224 {
225 _parentLo.SetLineGrowth( 0, !y );
226 _parentLo.SetLineGrowth( 2, !y );
227 _parentLo.SetLineGrowth( 1, y );
228 _parentLo.SetColGrowth( 0, !x );
229 _parentLo.SetColGrowth( 2, !x );
230 _parentLo.SetColGrowth( 1, x );
231 Parent()->RecalcLayouts();
232 }
233 }
234
SetPosition()235 void NCDialog::SetPosition()
236 {
237
238 if ( Type() == WT_CHILD )
239 {
240 LSize ls = _lo.GetLSize();
241 // ls.x.maximal = ls.x.minimal;
242 // ls.y.maximal = ls.y.minimal;
243 SetLSize( ls );
244
245 if ( Parent() )
246 {
247 Parent()->RecalcLayouts();
248 }
249
250 return;
251 }
252
253
254 LSize ls = _lo.GetLSize();
255
256 crect r = Rect();
257
258 int w = ls.x.ideal > 0 ? ls.x.ideal : 20;
259 int h = ls.y.ideal > 0 ? ls.y.ideal : 20;
260
261 r.right = r.left + w;
262 r.bottom = r.top + h;
263
264 Win* parent = Parent();
265
266 if ( parent )
267 {
268 crect pr = parent->Rect();
269
270 int w = r.Width();
271 int h = r.Height();
272
273 int dx = ( pr.Width() - w ) / 2;
274 int dy = ( pr.Height() - h ) / 2;
275
276
277 r.left = pr.left + dx;
278 r.right = r.left + w;
279 r.top = pr.top + dy;
280 r.bottom = r.top + h;
281
282 }
283
284 Move( r );
285 }
286
EventClose()287 bool NCDialog::EventClose()
288 {
289 CloseDialog( CMD_CANCEL );
290 return false;
291 }
292
EventSize(cevent_size * pEvent)293 void NCDialog::EventSize( cevent_size* pEvent )
294 {
295 if ( Type() == WT_CHILD && Parent() )
296 {
297 SetPosition();
298 crect r = Rect();
299 r.left += 10;
300 r.top += 10;
301 r.right += 10;
302 r.bottom += 10;
303
304 if ( r != _shadow.Rect() ) { _shadow.Move( r ); }
305
306 }
307
308 Win::EventSize( pEvent );
309 }
310
311
EventMove(cevent_move * pEvent)312 void NCDialog::EventMove( cevent_move* pEvent )
313 {
314 if ( Type() == WT_CHILD && Parent() )
315 {
316 SetPosition();
317 crect r = Rect();
318 r.left += 10;
319 r.top += 10;
320 r.right += 10;
321 r.bottom += 10;
322
323 if ( r != _shadow.Rect() ) { _shadow.Move( r ); }
324
325 }
326
327 Win::EventMove( pEvent );
328 }
329
330
EventKey(cevent_key * pEvent)331 bool NCDialog::EventKey( cevent_key* pEvent )
332 {
333 if ( pEvent->Type() == EV_KEYDOWN && pEvent->Key() == VK_ESCAPE )
334 {
335 OnCancel();
336 return true;
337 };
338
339 return Win::EventKey( pEvent );
340 }
341
GetFocusButtonNum()342 int NCDialog::GetFocusButtonNum()
343 {
344 for ( int i = 0; i < _bList.count(); i++ )
345 if ( _bList[i]->InFocus() ) { return i; }
346
347 return -1;
348 }
349
EventChildKey(Win * child,cevent_key * pEvent)350 bool NCDialog::EventChildKey( Win* child, cevent_key* pEvent )
351 {
352 if ( pEvent->Type() == EV_KEYDOWN )
353 {
354 //dbg_printf("key=0x%x\n",pEvent->Key());
355 if ( pEvent->Key() == VK_ESCAPE )
356 {
357 OnCancel();
358 return true;
359 }
360
361 if ( pEvent->Key() == VK_TAB )
362 {
363 if ( ( pEvent->Mod() & KM_SHIFT ) != 0 )
364 {
365 FocusPrevChild();
366 }
367 else
368 {
369 FocusNextChild();
370 }
371
372 return true;
373 }
374
375 // on UNIX shift-tab gives XK_ISO_Left_Tab
376 #ifdef XK_ISO_Left_Tab
377 else if ( pEvent->Key() == XK_ISO_Left_Tab )
378 {
379 FocusPrevChild();
380 return true;
381 }
382
383 #endif // XK_ISO_Left_Tab
384 else if ( pEvent->Key() == VK_RETURN || pEvent->Key() == VK_NUMPAD_RETURN )
385 {
386 if ( enterCmd && GetFocusButtonNum() < 0 )
387 {
388 CloseDialog( enterCmd );
389 return true;
390 }
391 }
392 else if ( pEvent->Key() == VK_LEFT || pEvent->Key() == VK_RIGHT )
393 {
394 int i = GetFocusButtonNum();
395
396 if ( i >= 0 )
397 {
398 int n;
399
400 if ( pEvent->Key() == VK_LEFT )
401 {
402 n = i ? i - 1 : _bList.count() - 1;
403 }
404 else
405 {
406 n = ( ( i + 1 ) % _bList.count() );
407 }
408
409 if ( n != i )
410 {
411 _bList[n]->SetFocus();
412 }
413
414 return true;
415 }
416 }
417
418 };
419
420 return Win::EventChildKey( child, pEvent );
421 }
422
423 //namespace wal {
424 //extern Display* display;
425 //};
426
EventShow(bool show)427 bool NCDialog::EventShow( bool show )
428 {
429 if ( show && Type() == WT_CHILD && Parent() )
430 {
431 SetPosition();
432 crect r = Rect();
433 _shadow.Move( crect( r.left + 10, r.top + 10, 10 + r.right, 10 + r.bottom ) );
434 _shadow.Show( SHOW_INACTIVE );
435 _shadow.OnTop();
436 }
437
438 OnTop();
439 SetFocus();
440
441 return Win::EventShow( show );
442 }
443
444
Paint(wal::GC & gc,const crect & paintRect)445 void NCDialog::Paint( wal::GC& gc, const crect& paintRect )
446 {
447 int bcolor = UiGetColor( uiBackground, 0, 0, 0x808080 );
448
449 gc.SetFillColor( bcolor );
450 gc.FillRect( _borderRect );
451 Draw3DButtonW2( gc, _borderRect, bcolor, true );
452 crect rect = _frameRect;
453 Draw3DButtonW2( gc, _frameRect, bcolor, false );
454 rect.Dec();
455 rect.Dec();
456 DrawBorder( gc, rect, 0 );
457 }
458
459
~NCDialog()460 NCDialog::~NCDialog()
461 {
462 if ( Type() == WT_CHILD && Parent() )
463 {
464 ( ( NCDialogParent* )Parent() )->DeleteLayout( &_parentLo );
465 }
466 }
467
468 /////////////////////////////////// NCVertDialog
469
EventChildKey(Win * child,cevent_key * pEvent)470 bool NCVertDialog::EventChildKey( Win* child, cevent_key* pEvent )
471 {
472 // try to preprocess key combinations like Cntrl + VK_DOWN
473 if ( dynamic_cast<ComboBox*>(child) && child->EventKey(pEvent) )
474 {
475 return true;
476 }
477
478 if ( pEvent->Type() == EV_KEYDOWN )
479 {
480 if ( pEvent->Key() == VK_UP || pEvent->Key() == VK_DOWN )
481 {
482 int n = -1;
483 int count = order.count();
484 Win* button = GetDownButton();
485
486 if ( button ) { count++; }
487
488 for ( int i = 0; i < order.count(); i++ ) if ( order[i]->InFocus() ) { n = i; break; }
489
490 if ( pEvent->Key() == VK_UP )
491 {
492 n = ( n + count - 1 ) % count;
493 }
494 else if ( pEvent->Key() == VK_DOWN )
495 {
496 n = ( n + 1 ) % count;
497 }
498
499 if ( n >= 0 && n < order.count() )
500 {
501 order[n]->SetFocus();
502 }
503 else if ( button ) { button->SetFocus(); }
504
505 return true;
506 }
507 }
508
509 return NCDialog::EventChildKey( child, pEvent );
510 }
511
512
~NCVertDialog()513 NCVertDialog::~NCVertDialog() {}
514
515 /*
516 //for ltext
517 _LT("DB>Ok")
518 _LT("DB>Cancel")
519 _LT("DB>Yes")
520 _LT("DB>No")
521 */
522
523 char OkButtonText[] = "O&k";
524 char CancelButtonText[] = "&Cancel";
525 char PanelButtonText[] = "&Panel";
526 char YesButtonText[] = "&Yes";
527 char NoButtonText[] = "&No";
528
529 ButtonDataNode bListOk[] = { {OkButtonText, CMD_OK}, {0, 0}};
530 ButtonDataNode bListCancel[] = { {CancelButtonText, CMD_CANCEL}, {0, 0}};
531 ButtonDataNode bListOkCancel[] = { {OkButtonText, CMD_OK}, {CancelButtonText, CMD_CANCEL}, {0, 0}};
532 ButtonDataNode bListOkCancelPanel[] = { { OkButtonText, CMD_OK }, { CancelButtonText, CMD_CANCEL }, { PanelButtonText, CMD_PUT_RESULTS_TO_TEMP_PANEL }, { 0, 0 } };
533 ButtonDataNode bListYesNoCancel[] = { {YesButtonText, CMD_YES}, {NoButtonText, CMD_NO}, {CancelButtonText, CMD_CANCEL}, {0, 0}};
534
535 char cmdKillTxt[] = " kill ";
536 char cmdKill9Txt[] = " kill -9 ";
537
538 ButtonDataNode bListKill[] = { {CancelButtonText, CMD_CANCEL}, {cmdKillTxt, CMD_KILL}, {cmdKill9Txt, CMD_KILL_9}, {0, 0}};
539
540 int uiNCMessageBox = GetUiID( "messagebox" );
541 int uiNCRedMessageBox = GetUiID( "messagebox-red" );
542
NCMessageBox(NCDialogParent * parent,const char * utf8head,const char * utf8txt,bool red,ButtonDataNode * buttonList)543 int NCMessageBox( NCDialogParent* parent, const char* utf8head, const char* utf8txt, bool red, ButtonDataNode* buttonList )
544 {
545 std::vector<unicode_t> str = utf8_to_unicode( utf8txt );
546 ccollect<unicode_t> buf;
547
548 unicode_t* s = str.data();
549 int lLine = 0;
550
551 for ( ; *s; s++ )
552 {
553 if ( lLine > 100 )
554 {
555 buf.append( '\n' );
556 lLine = 0;
557 }
558
559 if ( *s == '\n' )
560 {
561 lLine = 0;
562 }
563
564 buf.append( *s );
565 lLine++;
566 }
567
568 buf.append( 0 );
569
570
571 NCDialog d( ::createDialogAsChild, red ? uiNCRedMessageBox : uiNCMessageBox, parent, utf8_to_unicode( utf8head ).data(), buttonList ); //, red ? 0xFF:0xD8E9EC, red ? 0xFFFFFF :0x1);
572 StaticLine text( 0, &d, buf.ptr() );
573
574 text.Show();
575 text.Enable();
576 Layout lo( 3, 3 );
577 lo.LineSet( 0, 5 );
578 lo.LineSet( 2, 5 );
579 lo.ColSet( 0, 15 );
580 lo.ColSet( 2, 15 );
581 lo.AddWin( &text, 1, 1 );
582 d.AddLayout( &lo );
583
584 d.SetPosition();
585 return d.DoModal();
586 }
587
588
589 class GoToDialog: public NCVertDialog
590 {
591 EditLine edit;
592 public:
GoToDialog(int nId,NCDialogParent * parent)593 GoToDialog( int nId, NCDialogParent* parent )
594 : NCVertDialog( ::createDialogAsChild, nId, parent, utf8_to_unicode( "Go to line" ).data(), bListOkCancel ), //0xD8E9EC, 0),
595 edit( 0, ( Win* )this, 0, 0 )
596 {
597 edit.Enable();
598 edit.Show();
599 AddWin( &edit );
600 order.append( &edit );
601 edit.SetFocus();
602 SetPosition();
603 }
604
GetText()605 std::vector<unicode_t> GetText() { return edit.GetText(); };
606
607 virtual ~GoToDialog();
608 };
609
~GoToDialog()610 GoToDialog::~GoToDialog() {}
611
612
GoToLineDialog(NCDialogParent * parent)613 int GoToLineDialog( NCDialogParent* parent )
614 {
615 GoToDialog d( 0, parent );
616 d.SetEnterCmd( CMD_OK );
617 int r = d.DoModal();
618
619 if ( r != CMD_OK ) { return -1; }
620
621 std::vector<unicode_t> str = d.GetText();
622 int n = 0;
623 unicode_t* s = str.data();
624
625 while ( *s == ' ' ) { s++; }
626
627 for ( ; *s >= '0' && *s <= '9'; s++ )
628 {
629 n = n * 10 + *s - '0';
630 }
631
632 return n;
633 }
634
635 class clInputStrDialogBase : public NCVertDialog
636 {
637 public:
clInputStrDialogBase(NCDialogParent * Parent,const unicode_t * Message)638 clInputStrDialogBase( NCDialogParent* Parent, const unicode_t* Message )
639 : NCVertDialog( ::createDialogAsChild, 0, Parent, Message, bListOkCancel )
640 {
641 }
~clInputStrDialogBase()642 virtual ~clInputStrDialogBase() {}
643
644 virtual std::vector<unicode_t> GetText() const = 0;
645
646 virtual std::vector<unicode_t> ShowDialog();
647 };
648
ShowDialog()649 std::vector<unicode_t> clInputStrDialogBase::ShowDialog()
650 {
651 SetEnterCmd( CMD_OK );
652
653 if ( DoModal() != CMD_OK )
654 {
655 return std::vector<unicode_t>();
656 }
657
658 return GetText();
659 }
660
661
662 class clInputStrDialog : public clInputStrDialogBase
663 {
664 private:
665 EditLine m_StrEdit;
666
667 public:
clInputStrDialog(NCDialogParent * Parent,const unicode_t * Message,const unicode_t * Str)668 clInputStrDialog( NCDialogParent* Parent, const unicode_t* Message, const unicode_t* Str )
669 : clInputStrDialogBase( Parent, Message )
670 , m_StrEdit( 0, (Win*) this, 0, 0, 100 )
671 {
672 m_StrEdit.Enable();
673 m_StrEdit.Show();
674 AddWin( &m_StrEdit );
675 order.append( &m_StrEdit );
676
677 if ( Str )
678 {
679 m_StrEdit.SetText( Str, true );
680 }
681
682 m_StrEdit.SetFocus();
683 SetPosition();
684 }
~clInputStrDialog()685 virtual ~clInputStrDialog() {}
686
GetText() const687 virtual std::vector<unicode_t> GetText() const override
688 {
689 return m_StrEdit.GetText();
690 }
691 };
692
693
694 class clInputFieldDialog : public clInputStrDialogBase
695 {
696 private:
697 clNCEditLine m_FieldEdit;
698
699 public:
clInputFieldDialog(const char * FieldName,NCDialogParent * Parent,const unicode_t * Message,const unicode_t * Str)700 clInputFieldDialog( const char* FieldName, NCDialogParent* Parent, const unicode_t* Message, const unicode_t* Str )
701 : clInputStrDialogBase( Parent, Message )
702 , m_FieldEdit( FieldName, 0, (Win*)this, 0, 100, 7 )
703 {
704 m_FieldEdit.Enable();
705 m_FieldEdit.Show();
706 AddWin( &m_FieldEdit );
707 order.append( &m_FieldEdit );
708
709 if ( Str )
710 {
711 m_FieldEdit.SetText( Str, true );
712 }
713
714 m_FieldEdit.SetFocus();
715 SetPosition();
716 }
~clInputFieldDialog()717 virtual ~clInputFieldDialog() {}
718
GetText() const719 virtual std::vector<unicode_t> GetText() const override
720 {
721 return m_FieldEdit.GetText();
722 }
723
ShowDialog()724 virtual std::vector<unicode_t> ShowDialog() override
725 {
726 std::vector<unicode_t> Res = clInputStrDialogBase::ShowDialog();
727 if ( Res.size() > 0 )
728 {
729 m_FieldEdit.AddCurrentTextToHistory();
730 }
731
732 return Res;
733 }
734 };
735
736
InputStringDialog(NCDialogParent * Parent,const unicode_t * Message,const unicode_t * Str)737 std::vector<unicode_t> InputStringDialog( NCDialogParent* Parent, const unicode_t* Message, const unicode_t* Str )
738 {
739 return InputStringDialog( nullptr, Parent, Message, Str );
740 }
741
InputStringDialog(const char * FieldName,NCDialogParent * Parent,const unicode_t * Message,const unicode_t * Str)742 std::vector<unicode_t> InputStringDialog( const char* FieldName, NCDialogParent* Parent, const unicode_t* Message, const unicode_t* Str )
743 {
744 if ( !FieldName )
745 {
746 clInputStrDialog Dlg( Parent, Message, Str );
747 return Dlg.ShowDialog();
748 }
749
750 clInputFieldDialog Dlg( FieldName, Parent, Message, Str );
751 return Dlg.ShowDialog();
752 }
753
754 int uiKillCmdDialog = GetUiID( "KillCmdDialog" );
755
KillCmdDialog(NCDialogParent * parent,const unicode_t * cmd)756 int KillCmdDialog( NCDialogParent* parent, const unicode_t* cmd )
757 {
758 NCDialog d( ::createDialogAsChild, uiKillCmdDialog, parent, utf8_to_unicode( "Kill command" ).data(), bListKill ); //, 0xD8E9EC, 0);
759 StaticLine text( 0, &d, cmd );
760
761 text.Show();
762 text.Enable();
763 Layout lo( 3, 3 );
764 lo.LineSet( 0, 5 );
765 lo.LineSet( 2, 5 );
766 lo.ColSet( 0, 15 );
767 lo.ColSet( 2, 15 );
768 lo.AddWin( &text, 1, 1 );
769 d.AddLayout( &lo );
770
771 d.SetPosition();
772 return d.DoModal();
773
774 }
775
776 ////////////////////////////////////////////////////////////////////////////
777
CmdHistoryDialog(int nId,NCDialogParent * parent,NCHistory & history)778 CmdHistoryDialog::CmdHistoryDialog( int nId, NCDialogParent* parent, NCHistory& history )
779 : NCDialog( createDialogAsChild, nId, parent, utf8_to_unicode( " History " ).data(), bListOkCancel ),
780 _history( history ),
781 _selected( history.Count() - 1 ),
782 _list( Win::WT_CHILD, Win::WH_TABFOCUS | WH_CLICKFOCUS, 0, this, VListWin::SINGLE_SELECT, VListWin::BORDER_3D, 0 )
783 {
784 for ( int i = _history.Count() - 1; i >= 0; i-- ) { _list.Append( _history[i] ); }
785
786 _list.Enable();
787 _list.Show();
788 _list.SetFocus();
789 LSRange h( 10, 1000, 10 );
790 LSRange w( 50, 1000, 30 );
791 _list.SetHeightRange( h ); //in characters
792 _list.SetWidthRange( w ); //in characters
793
794 if ( _history.Count() > 0 )
795 {
796 _list.MoveFirst( 0 );
797 _list.MoveCurrent( _history.Count() - 1 );
798 }
799
800
801 AddWin( &_list );
802 SetEnterCmd( CMD_OK );
803 SetPosition();
804 };
805
806
Command(int id,int subId,Win * win,void * data)807 bool CmdHistoryDialog::Command( int id, int subId, Win* win, void* data )
808 {
809 if ( id == CMD_ITEM_CLICK && win == &_list )
810 {
811 EndModal( CMD_OK );
812 }
813
814 return NCDialog::Command( id, subId, win, data );
815 }
816
817 ////////////////////////////////////////////////////////////////////////////
NCDialogParent(Win::WTYPE t,unsigned hints,int nId,Win * _parent,const crect * rect)818 NCDialogParent::NCDialogParent( Win::WTYPE t, unsigned hints, int nId , Win* _parent , const crect* rect )
819 : OperThreadWin( t, hints, nId, _parent, rect ), _layout( 1, 1 )
820 {
821 _layout.SetLineGrowth( 0 );
822 _layout.SetColGrowth( 0 );
823 _layout.ColSet( 0, 32, 100000 );
824 _layout.LineSet( 0, 32, 100000 );
825 SetLayout( &_layout );
826 }
827
~NCDialogParent()828 NCDialogParent::~NCDialogParent() {}
829
830
831
832 //////////////////////////////////////////// DlgMenu
833
Add(const unicode_t * name,const unicode_t * comment1,const unicode_t * comment2,int cmd,int icon)834 void clMenuData::Add( const unicode_t* name, const unicode_t* comment1, const unicode_t* comment2, int cmd, int icon )
835 {
836 Node node;
837
838 if ( name ) { node.name = new_unicode_str( name ); }
839
840 if ( comment1 ) { node.comment1 = new_unicode_str( comment1 ); }
841
842 if ( comment2 ) { node.comment2 = new_unicode_str( comment2 ); }
843
844 node.cmd = cmd;
845 node.icon = icon;
846
847 list.append( node );
848 }
849
Add(const char * utf8name,const char * utf8coment1,const char * utf8coment2,int cmd,int icon)850 void clMenuData::Add( const char* utf8name, const char* utf8coment1, const char* utf8coment2, int cmd, int icon )
851 {
852 Add( utf8name ? utf8_to_unicode( utf8name ).data() : 0,
853 utf8coment1 ? utf8_to_unicode( utf8coment1 ).data() : 0,
854 utf8coment2 ? utf8_to_unicode( utf8coment2 ).data() : 0,
855 cmd,
856 icon
857 );
858 }
859
AddSplitter()860 void clMenuData::AddSplitter()
861 {
862 Node node;
863 node.cmd = 0;
864 list.append( node );
865 }
866
867 class clSelectDriveDlgMenu: public Win
868 {
869 clMenuData* _data;
870 int _current;
871 int _itemH;
872 int _width;
873 int _nameW, _comment1W, _comment2W;
874 int _splitterH;
875 int _splitterW;
876 public:
877 clSelectDriveDlgMenu( Win* parent, clMenuData* data );
878
879 void SetCurrent( int n, bool searchUp );
880
881 virtual bool EventKey( cevent_key* pEvent );
882 virtual void Paint( wal::GC& gc, const crect& paintRect );
883 virtual bool EventMouse( cevent_mouse* pEvent );
884 virtual bool EventShow( bool show );
885 virtual int UiGetClassId();
886 };
887
888
SetCurrent(int n,bool searchUp)889 void clSelectDriveDlgMenu::SetCurrent( int n, bool searchUp )
890 {
891 int count = _data->Count();
892
893 if ( count <= 0 ) { _current = -1; return; }
894
895 if ( n >= count ) { n = count - 1; }
896
897 if ( n <= 0 ) { n = 0; }
898
899 while ( n >= 0 && n < count )
900 {
901 if ( _data->list[n].cmd ) { break; }
902
903 n = n + ( searchUp ? -1 : 1 );
904 }
905
906 _current = n;
907 }
908
909 //int uiDlgMenu = GetUiID("DlgMenu");
UiGetClassId()910 int clSelectDriveDlgMenu::UiGetClassId()
911 {
912 return uiClassButton/*DlgMenu*/;
913 } //чтоб диалог его востринимал как кнопку
914
915
EventShow(bool show)916 bool clSelectDriveDlgMenu::EventShow( bool show )
917 {
918 if ( show ) { SetCapture(); }
919 else { ReleaseCapture(); }
920
921 return true;
922 }
923
924
clSelectDriveDlgMenu(Win * parent,clMenuData * data)925 clSelectDriveDlgMenu::clSelectDriveDlgMenu( Win* parent, clMenuData* data )
926 : Win( Win::WT_CHILD, Win::WH_TABFOCUS | Win::WH_CLICKFOCUS, parent )
927 , _data( data )
928 , _current( 0 )
929 , _itemH( 16 )
930 , _width( 50 )
931 , _nameW( 10 )
932 , _comment1W( 0 )
933 , _comment2W( 0 )
934 , _splitterH( 5 )
935 , _splitterW( 1 )
936 {
937 wal::GC gc( this );
938 gc.Set( GetFont() );
939
940 int w = 0;
941 int height = 0;
942
943 static unicode_t A[] = {'A', 'B', 'C'};
944 cpoint p = gc.GetTextExtents( A, 3 );
945 _itemH = p.y;
946
947 if ( _itemH < 16 ) { _itemH = 16; }
948
949 _splitterH = _itemH / 4;
950
951 if ( _splitterH < 3 ) { _splitterH = 3; }
952
953 for ( int i = 0 ; i < _data->Count(); i++ )
954 {
955 unicode_t* name = _data->list[i].name.data();
956
957 if ( _data->list[i].cmd != 0 )
958 {
959 if ( name )
960 {
961 cpoint p = gc.GetTextExtents( name );
962
963 if ( _nameW < p.x ) { _nameW = p.x; }
964 }
965
966 unicode_t* comment1 = _data->list[i].comment1.data();
967 unicode_t* comment2 = _data->list[i].comment2.data();
968
969 if ( comment1 )
970 {
971 cpoint p = gc.GetTextExtents( comment1 );
972
973 if ( _comment1W < p.x ) { _comment1W = p.x; }
974 }
975
976 if ( comment2 )
977 {
978 cpoint p = gc.GetTextExtents( comment2 );
979
980 if ( _comment2W < p.x ) { _comment2W = p.x; }
981 }
982
983 height += _itemH;
984 }
985 else
986 {
987 height += _splitterH;
988 }
989 }
990
991 w = 16 + 5 + _nameW + 5 + _comment1W + 30 + _comment2W;
992
993 if ( _width < w ) { _width = w; }
994
995 SetLSize( LSize( cpoint( _width, height ) ) );
996 }
997
EqFirst(const unicode_t * s,int c)998 inline bool EqFirst( const unicode_t* s, int c )
999 {
1000 return s && UnicodeLC( *s ) == c;
1001 }
1002
EventKey(cevent_key * pEvent)1003 bool clSelectDriveDlgMenu::EventKey( cevent_key* pEvent )
1004 {
1005 if ( _data->Count() && pEvent->Type() == EV_KEYDOWN )
1006 {
1007
1008 switch ( pEvent->Key() )
1009 {
1010 case VK_R:
1011 {
1012 bool IsCtrl = ( pEvent->Mod() & KM_CTRL ) != 0;
1013 if ( IsCtrl )
1014 {
1015 Command( ID_RESTART_DIALOG, 0, this, nullptr );
1016 return false;
1017 }
1018 break;
1019 }
1020
1021 case VK_UP:
1022 SetCurrent( _current - 1, true );
1023 break;
1024
1025 case VK_DOWN:
1026 SetCurrent( _current + 1, false );
1027 break;
1028
1029 case VK_HOME:
1030 case VK_LEFT:
1031 SetCurrent( 0, false );
1032 break;
1033
1034 case VK_END:
1035 case VK_RIGHT:
1036 SetCurrent( _data->Count() - 1, true ); ;
1037 break;
1038
1039 case VK_NUMPAD_RETURN:
1040 case VK_RETURN:
1041 if ( _current >= 0 && _current < _data->Count() && _data->list[_current].cmd != 0 )
1042 {
1043 Command( _data->list[_current].cmd, 0, this, 0 );
1044 }
1045
1046 break;
1047
1048 default:
1049 {
1050 unicode_t c = UnicodeLC( pEvent->Char() );
1051 int i;
1052 int n = 0;
1053 int count = _data->Count();
1054
1055 for ( i = 0; i < count; i++ )
1056 if ( EqFirst( _data->list[i].name.data(), c ) ) { n++; }
1057
1058 if ( n == 1 )
1059 {
1060 for ( i = 0; i < count; i++ )
1061 if ( EqFirst( _data->list[i].name.data(), c ) )
1062 {
1063 _current = i;
1064 Command( _data->list[i].cmd, 0, this, 0 );
1065 break;
1066 };
1067
1068 break;
1069 }
1070
1071 if ( n > 1 )
1072 {
1073 for ( i = _current + 1; i < count; i++ )
1074 if ( EqFirst( _data->list[i].name.data(), c ) ) { goto t; }
1075
1076 for ( i = 0; i <= _current && i < count; i++ )
1077 if ( EqFirst( _data->list[i].name.data(), c ) ) { goto t; }
1078
1079 t:
1080 ;
1081 _current = i;
1082 break;
1083 }
1084
1085 }
1086
1087 return Win::EventKey( pEvent );
1088 }
1089
1090 Invalidate();
1091 };
1092
1093 return Win::EventKey( pEvent );
1094 }
1095
1096
EventMouse(cevent_mouse * pEvent)1097 bool clSelectDriveDlgMenu::EventMouse( cevent_mouse* pEvent )
1098 {
1099 switch ( pEvent->Type() )
1100 {
1101 case EV_MOUSE_MOVE:
1102 break;
1103
1104 case EV_MOUSE_PRESS:
1105 case EV_MOUSE_DOUBLE:
1106 {
1107 cpoint p = pEvent->Point();
1108 int count = _data->Count();
1109
1110 if ( !count || p.x < 0 || p.x > _width || p.y < 0 )
1111 {
1112 Command( CMD_CANCEL, 0, this, 0 );
1113 return true;
1114 }
1115
1116 if ( pEvent->Button() != MB_L ) { break; }
1117
1118 int n = -1;
1119 int h = 0;
1120
1121 for ( int i = 0; i < _data->Count(); i++ )
1122 {
1123 int ih = _data->list[i].cmd ? _itemH : _splitterH;
1124
1125 if ( p.y < h + ih )
1126 {
1127 if ( _data->list[i].cmd != 0 ) { n = i; }
1128
1129 break;
1130 }
1131
1132 h += ih;
1133 }
1134
1135 if ( n >= 0 )
1136 {
1137 _current = n;
1138 Invalidate();
1139 Command( _data->list[n].cmd, 0, this, 0 );
1140 }
1141 }
1142 break;
1143
1144 case EV_MOUSE_RELEASE:
1145 break;
1146 };
1147
1148 return true;
1149 }
1150
1151 static int uiFcColor = GetUiID( "first-char-color" );
1152 static int uiCommentColor = GetUiID( "comment-color" );
1153
Paint(wal::GC & gc,const crect & paintRect)1154 void clSelectDriveDlgMenu::Paint( wal::GC& gc, const crect& paintRect )
1155 {
1156 cfont* font = GetFont();
1157 gc.Set( font );
1158 int y = 0;
1159
1160 int bgColor = UiGetColor( uiBackground, 0, 0, 0xB0B000 );
1161
1162 int count = _data->Count();
1163
1164 int Splitters = 0;
1165 int SplitterTop = 0;
1166 int SplitterBottom = 0;
1167
1168 for ( int i = 0; i < count; i++ )
1169 {
1170 if ( _data->list[i].cmd == 0 )
1171 {
1172 gc.SetFillColor( bgColor );
1173 gc.FillRect( crect( 0, y, _width, y + _splitterH ) );
1174 crect rect( 0, y + 1, 0 + _width, y + 2 );
1175 gc.SetFillColor( ColorTone( bgColor, -150 ) );
1176 gc.FillRect( rect );
1177 rect.top += 1;
1178 rect.bottom += 1;
1179 gc.SetFillColor( ColorTone( bgColor, +50 ) );
1180 gc.FillRect( rect );
1181 y += _splitterH;
1182 Splitters++;
1183
1184 if ( Splitters == 1 ) { SplitterTop = y; }
1185
1186 if ( Splitters == 2 ) { SplitterBottom = y - _splitterH; }
1187 }
1188 else
1189 {
1190 UiCondList ucl;
1191
1192 if ( i == _current ) { ucl.Set( uiCurrentItem, true ); }
1193
1194 unsigned bg = UiGetColor( uiBackground, uiItem, &ucl, 0xFFFFFF );
1195 unsigned textColor = UiGetColor( uiColor, uiItem, &ucl, 0 );
1196 unsigned fcColor = UiGetColor( uiFcColor, uiItem, &ucl, 0xFF );
1197 unsigned commentColor = UiGetColor( uiCommentColor, uiItem, &ucl, 0 );
1198
1199 gc.SetFillColor( bg );
1200 gc.FillRect( crect( 0, y, _width, y + _itemH ) );
1201
1202 cicon icon;
1203
1204 if ( _data->list[i].icon >= 0 )
1205 {
1206 icon.Load( _data->list[i].icon, 16, 16 );
1207 }
1208 else
1209 {
1210 icon.Load( _data->list[i].cmd, 16, 16 );
1211 }
1212
1213 gc.DrawIcon( 0, y, &icon );
1214 gc.SetTextColor( textColor );
1215 int x = 16 + 5;
1216
1217 const unicode_t* name = _data->list[i].name.data();
1218 const unicode_t* comment1 = _data->list[i].comment1.data();
1219 const unicode_t* comment2 = _data->list[i].comment2.data();
1220
1221 if ( name )
1222 {
1223 gc.TextOutF( x, y, name );
1224 gc.SetTextColor( fcColor );
1225 gc.TextOutF( x, y, name, 1 );
1226 }
1227
1228 if ( comment1 )
1229 {
1230 gc.SetTextColor( commentColor );
1231 gc.TextOutF( x + _nameW + 5, y, comment1 );
1232 }
1233
1234 if ( comment2 )
1235 {
1236 gc.SetTextColor( commentColor );
1237 gc.TextOutF( x + _nameW + 5 + _comment1W + 30, y, comment2 );
1238 }
1239
1240 y += _itemH;
1241 }
1242 }
1243
1244 if ( _comment2W && SplitterTop && SplitterBottom )
1245 {
1246 int cx = _nameW + 5 + _comment1W + 30;
1247 gc.SetFillColor( ColorTone( bgColor, -150 ) );
1248 gc.FillRect( crect( cx, SplitterTop, cx + _splitterW, SplitterBottom ) );
1249 }
1250 }
1251
RunDldMenu(int nUi,NCDialogParent * parent,const char * header,clMenuData * data)1252 int RunDldMenu( int nUi, NCDialogParent* parent, const char* header, clMenuData* data )
1253 {
1254 if ( !data || data->Count() <= 0 ) { return CMD_CANCEL; }
1255
1256 NCDialog dlg( true, nUi, parent, utf8_to_unicode( header ).data(), 0 ); //, ::g_WcmConfig.whiteStyle ? 0xD8E9EC : 0xB0B000, 0xFFFFFF);
1257 clSelectDriveDlgMenu mtable( &dlg, data );
1258 mtable.Show();
1259 mtable.Enable();
1260 mtable.SetFocus();
1261 dlg.AddWin( &mtable );
1262 int Result = dlg.DoModal();
1263 return Result;
1264 }
1265
1266