25 #define YUILogComponent "ncurses" 26 #include <yui/YUILog.h> 29 #include "NCPopupInfo.h" 30 #include "NCMenuButton.h" 31 #include <yui/YShortcut.h> 32 #include "NCtoY2Event.h" 33 #include "YNCursesUI.h" 34 #include <yui/YDialogSpy.h> 35 #include <yui/YDialog.h> 40 static bool hiddenMenu()
42 return getenv(
"Y2NCDBG" ) != NULL;
46 NCDialog::NCDialog( YDialogType dialogType,
47 YDialogColorMode colorMode )
48 : YDialog( dialogType, colorMode )
57 yuiDebug() <<
"Constructor NCDialog(YDialogType t, YDialogColorMode c)" << std::endl;
62 NCDialog::NCDialog( YDialogType dialogType,
const wpos at,
const bool boxed )
63 : YDialog( dialogType, YDialogNormalColor )
69 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
72 yuiDebug() <<
"Constructor NCDialog(YDialogType t, const wpos at, const bool boxed)" << std::endl;
77 void NCDialog::_init()
79 NCurses::RememberDlg(
this );
85 if ( colorMode() == YDialogWarnColor )
87 mystyleset = NCstyle::WarnStyle;
89 else if ( colorMode() == YDialogInfoColor )
91 mystyleset = NCstyle::InfoStyle;
95 mystyleset = NCstyle::PopupStyle;
99 mystyleset = NCstyle::DefaultStyle;
102 dlgstyle = &NCurses::style()[mystyleset];
104 eventReason = YEvent::UnknownReason;
105 yuiDebug() <<
"+++ " <<
this << std::endl;
109 void NCDialog::_init_size()
111 defsze.H = NCurses::lines();
112 defsze.W = NCurses::cols();
113 hshaddow = vshaddow =
false;
144 NCDialog::~NCDialog()
146 NCurses::ForgetDlg(
this );
148 yuiDebug() <<
"--+START destroy " <<
this << std::endl;
150 if ( pan && !pan->
hidden() )
161 yuiDebug() <<
"---destroyed " <<
this << std::endl;
166 int NCDialog::preferredWidth()
168 if ( dialogType() == YMainDialog || ! hasChildren() )
169 return wGetDefsze().W;
175 csze =
wsze( firstChild()->preferredHeight(),
176 firstChild()->preferredWidth() );
179 csze = wsze::min( wGetDefsze(), wsze::max( csze,
wsze( 1 ) ) );
185 int NCDialog::preferredHeight()
187 if ( dialogType() == YMainDialog || ! hasChildren() )
189 return wGetDefsze().H;
196 csze =
wsze( firstChild()->preferredHeight(),
197 firstChild()->preferredWidth() );
200 csze = wsze::min( wGetDefsze(),
201 wsze::max( csze,
wsze( 1 ) ) );
207 void NCDialog::setSize(
int newwidth,
int newheight )
209 wRelocate(
wpos( 0 ),
wsze( newheight, newwidth ) );
210 yuiDebug() <<
"setSize() called: width: " << newwidth <<
" height: " << newheight << std::endl;
211 YDialog::setSize( newwidth, newheight );
215 void NCDialog::initDialog()
219 yuiDebug() <<
"setInitialSize() called!" << std::endl;
231 void NCDialog::showDialog()
233 yuiDebug() <<
"sd+ " <<
this << std::endl;
235 if ( pan && pan->
hidden() )
237 YPushButton *defaultB = YDialog::defaultButton();
241 defaultB->setKeyboardFocus();
247 DumpOn( yuiDebug(),
" " );
252 yuiMilestone() <<
"no pan" << std::endl;
257 yuiDebug() <<
"sd- " <<
this << std::endl;
261 void NCDialog::closeDialog()
263 yuiDebug() <<
"cd+ " <<
this << std::endl;
266 if ( pan && !pan->
hidden() )
270 yuiDebug() <<
this << std::endl;
273 yuiDebug() <<
"cd+ " <<
this << std::endl;
279 if ( active != newactive || ( pan && pan->
hidden() ) )
293 NCurses::SetStatusLine( describeFunctionKeys() );
295 yuiDebug() <<
this << std::endl;
314 void NCDialog::wMoveTo(
const wpos & newpos )
316 yuiDebug() << DLOC <<
this << newpos << std::endl;
320 void NCDialog::wCreate(
const wrect & newrect )
323 throw NCError(
"wCreate: already have win" );
325 wrect panrect( newrect );
331 switch ( NCurses::lines() - panrect.Sze.H )
347 switch ( NCurses::cols() - panrect.Sze.W )
364 if ( popedpos.L >= 0 )
366 if ( popedpos.L + panrect.Sze.H <= NCurses::lines() )
367 panrect.Pos.L = popedpos.L;
369 panrect.Pos.L = NCurses::lines() - panrect.Sze.H;
373 panrect.Pos.L = ( NCurses::lines() - panrect.Sze.H ) / 2;
376 if ( popedpos.C >= 0 )
378 if ( popedpos.C + panrect.Sze.W <= NCurses::cols() )
379 panrect.Pos.C = popedpos.C;
381 panrect.Pos.C = NCurses::cols() - panrect.Sze.W;
385 panrect.Pos.C = ( NCurses::cols() - panrect.Sze.W ) / 2;
388 if ( panrect.Pos.L + panrect.Sze.H < NCurses::lines() )
394 if ( panrect.Pos.C + panrect.Sze.W < NCurses::cols() )
412 panrect.Pos.L, panrect.Pos.C,
420 inparent.Sze.H, inparent.Sze.W,
421 inparent.Pos.L, inparent.Pos.C,
423 win->nodelay(
true );
425 yuiDebug() << DLOC << panrect <<
'(' << inparent <<
')' 426 <<
'[' << popedpos <<
']' << std::endl;
430 void NCDialog::wRedraw()
436 pan->
bkgdset( wStyle().getDlgBorder( active ).text );
438 if ( pan->
height() != NCurses::lines()
439 || pan->
width() != NCurses::cols() )
456 pan->
maxy() - 1, pan->
maxx(), false );
464 pan->
maxy(), pan->
maxx() - 1, false );
473 pan->transparent( pan->
maxy(), 0 );
479 pan->transparent( 0, pan->
maxx() );
485 void NCDialog::wRecoded()
489 if ( &NCurses::style()[mystyleset] != dlgstyle )
491 dlgstyle = &NCurses::style()[mystyleset];
494 pan->
bkgdset( wStyle(). getDumb().text );
502 void NCDialog::startMultipleChanges()
508 void NCDialog::doneMultipleChanges()
510 if ( inMultiDraw_i > 1 )
517 NCurses::SetStatusLine( describeFunctionKeys() );
522 void NCDialog::setStatusLine()
524 NCurses::SetStatusLine( describeFunctionKeys() );
528 void NCDialog::wUpdate(
bool forced_br )
534 && ( pan->
hidden() || inMultiDraw_i ) )
537 NCWidget::wUpdate( forced_br );
541 void NCDialog::grabActive(
NCWidget * nactive )
543 if ( wActive && wActive != static_cast<NCWidget *>(
this ) )
544 wActive->grabRelease(
this );
546 if ( nactive && nactive != static_cast<NCWidget *>(
this ) )
547 nactive->grabSet(
this );
549 const_cast<NCWidget *&
>( wActive ) = nactive;
553 void NCDialog::grabNotify(
NCWidget * mgrab )
555 if ( wActive && wActive == mgrab )
557 yuiDebug() << DLOC << mgrab <<
" active " << std::endl;
560 if ( wActive && wActive == mgrab )
566 bool NCDialog::wantFocus(
NCWidget & ngrab )
568 return Activate( ngrab );
572 void NCDialog::wDelete()
576 yuiDebug() << DLOC <<
"+++ " <<
this << std::endl;
578 yuiDebug() << DLOC <<
"--- " <<
this << std::endl;
585 NCWidget * c = ( startwith.*Direction )(
true )->Value();
587 while ( c != &startwith && ( c->GetState() != NC::WSnormal || !c->winExist() ) )
589 if ( c->GetState() == NC::WSactive )
591 yuiWarning() <<
"multiple active widgets in dialog? " 592 << startwith <<
" <-> " << c << std::endl;
593 c->SetState( NC::WSnormal );
597 c = ( c->*Direction )(
true )->Value();
616 bool NCDialog::Activate(
NCWidget & nactive )
618 if ( nactive.GetState() == NC::WSactive )
621 if ( nactive.GetState() == NC::WSnormal )
623 if ( wActive->GetState() == NC::WSactive )
624 wActive->SetState( NC::WSnormal );
628 nactive.SetState( NC::WSactive );
631 grabActive( &nactive );
640 void NCDialog::Activate( SeekDir Direction )
645 if ( Direction == 0 )
647 if ( Activate( *wActive ) )
654 Activate( GetNormal( *wActive, Direction ) );
658 void NCDialog::Activate()
664 void NCDialog::Deactivate()
666 if ( wActive->GetState() == NC::WSactive )
668 wActive->SetState( NC::WSnormal );
673 void NCDialog::ActivateNext()
679 void NCDialog::ActivatePrev()
685 bool NCDialog::ActivateByKey(
int key )
691 switch ( c->Value()->GetState() )
696 if ( c->Value()->HasHotkey( key )
697 || c->Value()->HasFunctionHotkey( key ) )
699 Activate( *c->Value() );
705 if ( c->IsDescendantOf( buddy ) )
707 yuiDebug() <<
"BUDDY ACTIVATION FOR " << c->Value() << std::endl;
708 Activate( *c->Value() );
712 yuiDebug() <<
"DROP BUDDY on " << c->Value() << std::endl;
721 if ( c->Value()->HasHotkey( key )
722 || c->Value()->HasFunctionHotkey( key ) )
724 yuiDebug() <<
"DUMB HOT KEY " << key <<
" in " << c->Value() << std::endl;
738 wint_t NCDialog::getinput()
742 if ( NCstring::terminalEncoding() ==
"UTF-8" )
744 wint_t gotwch = WEOF;
745 int ret = ::get_wch( &gotwch );
767 int gotch = ::getch();
771 if (( KEY_MIN > gotch || KEY_MAX < gotch )
776 str +=
static_cast<char>( gotch );
778 NCstring::RecodeToWchar( str, NCstring::terminalEncoding(), &to );
781 if ( gotch != (
int )got )
786 yuiDebug() <<
"Recode: " << str <<
" (encoding: " << NCstring::terminalEncoding() <<
") " 788 <<
"to wint_t: " << got << std::endl;
805 wint_t NCDialog::getch(
int timeout_millisec )
809 if ( timeout_millisec < 0 )
812 ::nodelay( ::stdscr,
false );
817 else if ( timeout_millisec )
822 if ( timeout_millisec > 25000 )
825 timeout_millisec -= 25000;
829 if ( timeout_millisec < 100 )
835 ::halfdelay( timeout_millisec / 100 );
837 timeout_millisec = 0;
842 while ( got == WEOF && timeout_millisec > 0 );
849 ::nodelay( ::stdscr,
true );
853 if ( got == KEY_RESIZE )
855 NCurses::ResizeEvent();
861 got = NCDialog::getch( timeout_millisec );
863 while ( timeout_millisec < 0 && got == WEOF && --i );
870 bool NCDialog::flushTypeahead()
875 if ( eventReason == YEvent::ValueChanged ||
876 eventReason == YEvent::SelectionChanged )
878 yuiDebug() <<
"DON't flush input buffer - reason: " << eventReason << std::endl;
883 yuiDebug() <<
"Flush input buffer" << std::endl;
889 void NCDialog::idleInput()
893 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
898 yuiDebug() <<
"idle+ " <<
this << std::endl;
902 if ( flushTypeahead() )
911 yuiDebug() <<
"idle+ " <<
this << std::endl;
913 yuiDebug() <<
"idle- " <<
this << std::endl;
920 yuiDebug() <<
"poll+ " <<
this << std::endl;
924 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
925 return NCursesEvent::cancel;
933 yuiDebug() <<
this <<
" deactivate" << std::endl;
941 yuiDebug() <<
this <<
" activate" << std::endl;
947 eventReason = returnEvent.reason;
948 pendingEvent = NCursesEvent::none;
950 yuiDebug() <<
"poll- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
955 NCursesEvent NCDialog::userInput(
int timeout_millisec )
957 yuiDebug() <<
"user+ " <<
this << std::endl;
959 if ( flushTypeahead() )
966 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
967 return NCursesEvent::cancel;
970 processInput( timeout_millisec );
973 eventReason = returnEvent.reason;
974 pendingEvent = NCursesEvent::none;
976 yuiDebug() <<
"user- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
988 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1017 void NCDialog::processInput(
int timeout_millisec )
1019 yuiDebug() <<
"process+ " <<
this <<
" active " << wActive
1020 <<
" timeout_millisec " << timeout_millisec << std::endl;
1024 yuiDebug() <<
this <<
"(return pending event)" << std::endl;
1031 if ( wActive->GetState() != NC::WSactive )
1033 yuiDebug() <<
"noactive item => reactivate!" << std::endl;
1037 if ( wActive->GetState() != NC::WSactive )
1039 yuiDebug() <<
"still noactive item!" << std::endl;
1041 if ( timeout_millisec == -1 )
1043 pendingEvent = NCursesEvent::cancel;
1044 yuiDebug() << DLOC <<
this <<
"(std::set ET_CANCEL since noactive item on pollInput)" << std::endl;
1052 if ( timeout_millisec > 0 )
1054 usleep( timeout_millisec * 1000 );
1055 pendingEvent = NCursesEvent::timeout;
1066 yuiDebug() <<
"enter loop..." << std::endl;
1070 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1073 ch = getch( timeout_millisec );
1081 if ( timeout_millisec == -1 )
1082 pendingEvent = NCursesEvent::cancel;
1083 else if ( timeout_millisec > 0 )
1084 pendingEvent = NCursesEvent::timeout;
1101 yuiMilestone() <<
"Asking for widget ID" << std::endl;
1110 Activate( *button );
1111 pendingEvent = getInputEvent( KEY_RETURN );
1129 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1130 NCurses::ScreenShot();
1131 yuiMilestone() <<
this << std::endl;
1132 DumpOn( yuiMilestone(),
" " );
1133 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1140 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1141 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1143 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1149 YDialogSpy::showDialogSpy();
1173 pendingEvent = getInputEvent( KEY_SLEFT );
1177 pendingEvent = getInputEvent( KEY_SRIGHT );
1189 pendingEvent = getInputEvent( ch );
1195 pendingEvent = getInputEvent( hch );
1199 pendingEvent = getHotkeyEvent( hch );
1206 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1208 pendingEvent = getHotkeyEvent( ch );
1212 pendingEvent = getInputEvent( ch );
1223 yuiDebug() <<
"process- " <<
this <<
" active " << wActive << std::endl;
1231 if ( wActive->isValid() )
1233 ret = wHandleInput( ch );
1234 ret.widget = wActive;
1243 return wActive->wHandleInput( ch );
1251 if ( wActive->isValid() )
1253 ret = wHandleHotkey( key );
1254 ret.widget = wActive;
1263 if ( key >= 0 && ActivateByKey( key ) )
1264 return wActive->wHandleHotkey( key );
1266 return NCursesEvent::none;
1270 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog * OBJ )
1273 return STREAM << *OBJ;
1275 return STREAM <<
"(NoNCDialog)";
1288 std::map<int, NCstring> NCDialog::describeFunctionKeys( )
1290 std::map<int, NCstring> fkeys;
1294 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1296 if ( w && w->hasFunctionKey() && w->isEnabled() )
1301 fkeys[ w->functionKey()] =
NCstring(w->debugLabel());
1309 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog & OBJ )
1311 STREAM << (
const NCWidget & )OBJ <<
' ' << OBJ.pan
1312 << ( OBJ.active ?
"{A " :
"{i " ) << OBJ.pendingEvent;
1314 if ( OBJ.pendingEvent )
1315 STREAM << OBJ.pendingEvent.widget;
1317 return STREAM <<
'}';
1321 bool NCDialog::getInvisible()
1323 if ( !pan || pan->
hidden() )
1334 bool NCDialog::getVisible()
1336 if ( !pan || !pan->
hidden() )
1345 pan->transparent( pan->
maxy(), 0 );
1350 pan->transparent( 0, pan->
maxx() );
1357 void NCDialog::resizeEvent()
1367 void NCDialog::showHotkeyHelp()
1369 std::string old_textdomain = textdomain( NULL );
1370 setTextdomain(
"ncurses" );
1373 _(
"<h1>Advanced Hotkeys:</h1>" 1374 "<p><b>Shift-F1</b> Show a list of advanced hotkeys.</p>" 1375 "<p><b>Shift-F4</b> Change color schema.</p>" 1376 "<p><b>Ctrl-\\</b> Quit the application.</p>" 1377 "<p><b>Ctrl-L</b> Refresh screen.</p>" 1378 "<p><b>Ctrl-D F1</b> Show a list of advanced hotkeys.</p>" 1379 "<p><b>Ctrl-D Shift-D</b> Dump dialog to the log file as a screen shot.</p>" 1380 "<p><b>Ctrl-D Shift-Y</b> Open YDialogSpy to see the widget hierarchy.</p>" 1381 "<p>Depending on your desktop environment some of these key combinations <br/>might not work.</p>" ),
1385 setTextdomain( old_textdomain.c_str() );
virtual void openInternal()
Internal open() method: Initialize what is left over to initialize after all dialog children have bee...
int clear()
Clear the window.
virtual void activate()
Activate this dialog: Make sure that it is shown as the topmost dialog of this application and that i...
int height() const
Number of lines in this window.
int vline(int len, chtype ch=0)
Draw a vertical line of len characters with the given character.
void bkgdset(chtype ch)
Set the background property.
void show()
Show the panel, i.e.
virtual YEvent * pollEventInternal()
Check if a user event is pending.
int begx() const
Column of top left corner relative to stdscr.
int box()
Draw a box around the window with the given vertical and horizontal drawing characters.
YWidget * askSendWidgetID()
Open a pop-up dialog to ask the user for a widget ID and then send it with sendWidgetID().
int begy() const
Line of top left corner relative to stdscr.
static YNCursesUI * ui()
Access the global Y2NCursesUI.
int hline(int len, chtype ch=0)
Draw a horizontal line of len characters with the given character.
int copywin(NCursesWindow &win, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol, bool overlay=TRUE)
Overlay or overwrite the rectangle in win given by dminrow,dmincol, dmaxrow,dmaxcol with the rectangl...
bool hidden() const
Return TRUE if the panel is hidden, FALSE otherwise.
void hide()
Hide the panel.
Helper class for translating an NCurses event to a YEvent.
virtual YEvent * waitForEventInternal(int timeout_millisec)
Wait for a user event.
int maxx() const
Largest x coord in window.
int width() const
Number of columns in this window.
YEvent * propagate()
The reason of existence of this class: Translate the NCursesEvent to a YEvent.
int maxy() const
Largest y coord in window.