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 <yui/YDialogSpy.h>
34 #include <yui/YDialog.h>
39 static bool hiddenMenu()
41 return getenv(
"Y2NCDBG" ) != NULL;
45 NCDialog::NCDialog( YDialogType dialogType,
46 YDialogColorMode colorMode )
47 : YDialog( dialogType, colorMode )
56 yuiDebug() <<
"Constructor NCDialog(YDialogType t, YDialogColorMode c)" << std::endl;
61 NCDialog::NCDialog( YDialogType dialogType,
const wpos at,
const bool boxed )
62 : YDialog( dialogType, YDialogNormalColor )
68 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
71 yuiDebug() <<
"Constructor NCDialog(YDialogType t, const wpos at, const bool boxed)" << std::endl;
76 void NCDialog::_init()
78 NCurses::RememberDlg(
this );
84 if ( colorMode() == YDialogWarnColor )
86 mystyleset = NCstyle::WarnStyle;
88 else if ( colorMode() == YDialogInfoColor )
90 mystyleset = NCstyle::InfoStyle;
94 mystyleset = NCstyle::PopupStyle;
98 mystyleset = NCstyle::DefaultStyle;
101 dlgstyle = &NCurses::style()[mystyleset];
103 eventReason = YEvent::UnknownReason;
104 yuiDebug() <<
"+++ " <<
this << std::endl;
108 void NCDialog::_init_size()
110 defsze.H = NCurses::lines();
111 defsze.W = NCurses::cols();
112 hshaddow = vshaddow =
false;
143 NCDialog::~NCDialog()
145 NCurses::ForgetDlg(
this );
147 yuiDebug() <<
"--+START destroy " <<
this << std::endl;
149 if ( pan && !pan->
hidden() )
160 yuiDebug() <<
"---destroyed " <<
this << std::endl;
165 int NCDialog::preferredWidth()
167 if ( dialogType() == YMainDialog || ! hasChildren() )
168 return wGetDefsze().W;
174 csze =
wsze( firstChild()->preferredHeight(),
175 firstChild()->preferredWidth() );
178 csze = wsze::min( wGetDefsze(), wsze::max( csze,
wsze( 1 ) ) );
184 int NCDialog::preferredHeight()
186 if ( dialogType() == YMainDialog || ! hasChildren() )
188 return wGetDefsze().H;
195 csze =
wsze( firstChild()->preferredHeight(),
196 firstChild()->preferredWidth() );
199 csze = wsze::min( wGetDefsze(),
200 wsze::max( csze,
wsze( 1 ) ) );
206 void NCDialog::setSize(
int newwidth,
int newheight )
208 wRelocate(
wpos( 0 ),
wsze( newheight, newwidth ) );
209 yuiDebug() <<
"setSize() called: width: " << newwidth <<
" height: " << newheight << std::endl;
210 YDialog::setSize( newwidth, newheight );
214 void NCDialog::initDialog()
218 yuiDebug() <<
"setInitialSize() called!" << std::endl;
230 void NCDialog::showDialog()
232 yuiDebug() <<
"sd+ " <<
this << std::endl;
234 if ( pan && pan->
hidden() )
236 YPushButton *defaultB = YDialog::defaultButton();
240 defaultB->setKeyboardFocus();
246 DumpOn( yuiDebug(),
" " );
251 yuiMilestone() <<
"no pan" << std::endl;
256 yuiDebug() <<
"sd- " <<
this << std::endl;
260 void NCDialog::closeDialog()
262 yuiDebug() <<
"cd+ " <<
this << std::endl;
265 if ( pan && !pan->
hidden() )
269 yuiDebug() <<
this << std::endl;
272 yuiDebug() <<
"cd+ " <<
this << std::endl;
278 if ( active != newactive || ( pan && pan->
hidden() ) )
292 NCurses::SetStatusLine( describeFunctionKeys() );
294 yuiDebug() <<
this << std::endl;
313 void NCDialog::wMoveTo(
const wpos & newpos )
315 yuiDebug() << DLOC <<
this << newpos << std::endl;
319 void NCDialog::wCreate(
const wrect & newrect )
322 throw NCError(
"wCreate: already have win" );
324 wrect panrect( newrect );
330 switch ( NCurses::lines() - panrect.Sze.H )
346 switch ( NCurses::cols() - panrect.Sze.W )
363 if ( popedpos.L >= 0 )
365 if ( popedpos.L + panrect.Sze.H <= NCurses::lines() )
366 panrect.Pos.L = popedpos.L;
368 panrect.Pos.L = NCurses::lines() - panrect.Sze.H;
372 panrect.Pos.L = ( NCurses::lines() - panrect.Sze.H ) / 2;
375 if ( popedpos.C >= 0 )
377 if ( popedpos.C + panrect.Sze.W <= NCurses::cols() )
378 panrect.Pos.C = popedpos.C;
380 panrect.Pos.C = NCurses::cols() - panrect.Sze.W;
384 panrect.Pos.C = ( NCurses::cols() - panrect.Sze.W ) / 2;
387 if ( panrect.Pos.L + panrect.Sze.H < NCurses::lines() )
393 if ( panrect.Pos.C + panrect.Sze.W < NCurses::cols() )
411 panrect.Pos.L, panrect.Pos.C,
419 inparent.Sze.H, inparent.Sze.W,
420 inparent.Pos.L, inparent.Pos.C,
422 win->nodelay(
true );
424 yuiDebug() << DLOC << panrect <<
'(' << inparent <<
')'
425 <<
'[' << popedpos <<
']' << std::endl;
429 void NCDialog::wRedraw()
435 pan->
bkgdset( wStyle().getDlgBorder( active ).text );
437 if ( pan->
height() != NCurses::lines()
438 || pan->
width() != NCurses::cols() )
455 pan->
maxy() - 1, pan->
maxx(),
false );
463 pan->
maxy(), pan->
maxx() - 1,
false );
472 pan->transparent( pan->
maxy(), 0 );
478 pan->transparent( 0, pan->
maxx() );
484 void NCDialog::wRecoded()
488 if ( &NCurses::style()[mystyleset] != dlgstyle )
490 dlgstyle = &NCurses::style()[mystyleset];
493 pan->
bkgdset( wStyle(). getDumb().text );
501 void NCDialog::startMultipleChanges()
507 void NCDialog::doneMultipleChanges()
509 if ( inMultiDraw_i > 1 )
516 NCurses::SetStatusLine( describeFunctionKeys() );
521 void NCDialog::setStatusLine()
523 NCurses::SetStatusLine( describeFunctionKeys() );
527 void NCDialog::wUpdate(
bool forced_br )
533 && ( pan->
hidden() || inMultiDraw_i ) )
536 NCWidget::wUpdate( forced_br );
540 void NCDialog::grabActive(
NCWidget * nactive )
542 if ( wActive && wActive !=
static_cast<NCWidget *
>(
this ) )
543 wActive->grabRelease(
this );
545 if ( nactive && nactive !=
static_cast<NCWidget *
>(
this ) )
546 nactive->grabSet(
this );
548 const_cast<NCWidget *&
>( wActive ) = nactive;
552 void NCDialog::grabNotify(
NCWidget * mgrab )
554 if ( wActive && wActive == mgrab )
556 yuiDebug() << DLOC << mgrab <<
" active " << std::endl;
559 if ( wActive && wActive == mgrab )
565 bool NCDialog::wantFocus(
NCWidget & ngrab )
567 return Activate( ngrab );
571 void NCDialog::wDelete()
575 yuiDebug() << DLOC <<
"+++ " <<
this << std::endl;
577 yuiDebug() << DLOC <<
"--- " <<
this << std::endl;
584 NCWidget * c = ( startwith.*Direction )(
true )->Value();
586 while ( c != &startwith && ( c->GetState() != NC::WSnormal || !c->winExist() ) )
588 if ( c->GetState() == NC::WSactive )
590 yuiWarning() <<
"multiple active widgets in dialog? "
591 << startwith <<
" <-> " << c << std::endl;
592 c->SetState( NC::WSnormal );
596 c = ( c->*Direction )(
true )->Value();
615 bool NCDialog::Activate(
NCWidget & nactive )
617 if ( nactive.GetState() == NC::WSactive )
620 if ( nactive.GetState() == NC::WSnormal )
622 if ( wActive->GetState() == NC::WSactive )
623 wActive->SetState( NC::WSnormal );
627 nactive.SetState( NC::WSactive );
630 grabActive( &nactive );
639 void NCDialog::Activate( SeekDir Direction )
644 if ( Direction == 0 )
646 if ( Activate( *wActive ) )
653 Activate( GetNormal( *wActive, Direction ) );
657 void NCDialog::Activate()
663 void NCDialog::Deactivate()
665 if ( wActive->GetState() == NC::WSactive )
667 wActive->SetState( NC::WSnormal );
672 void NCDialog::ActivateNext()
678 void NCDialog::ActivatePrev()
684 bool NCDialog::ActivateByKey(
int key )
690 switch ( c->Value()->GetState() )
695 if ( c->Value()->HasHotkey( key )
696 || c->Value()->HasFunctionHotkey( key ) )
698 Activate( *c->Value() );
704 if ( c->IsDescendantOf( buddy ) )
706 yuiDebug() <<
"BUDDY ACTIVATION FOR " << c->Value() << std::endl;
707 Activate( *c->Value() );
711 yuiDebug() <<
"DROP BUDDY on " << c->Value() << std::endl;
720 if ( c->Value()->HasHotkey( key )
721 || c->Value()->HasFunctionHotkey( key ) )
723 yuiDebug() <<
"DUMB HOT KEY " << key <<
" in " << c->Value() << std::endl;
737 wint_t NCDialog::getinput()
741 if ( NCstring::terminalEncoding() ==
"UTF-8" )
743 wint_t gotwch = WEOF;
744 int ret = ::get_wch( &gotwch );
766 int gotch = ::getch();
770 if (( KEY_MIN > gotch || KEY_MAX < gotch )
775 str +=
static_cast<char>( gotch );
777 NCstring::RecodeToWchar( str, NCstring::terminalEncoding(), &to );
780 if ( gotch != (
int )got )
785 yuiDebug() <<
"Recode: " << str <<
" (encoding: " << NCstring::terminalEncoding() <<
") "
787 <<
"to wint_t: " << got << std::endl;
804 wint_t NCDialog::getch(
int timeout_millisec )
808 if ( timeout_millisec < 0 )
811 ::nodelay( ::stdscr,
false );
816 else if ( timeout_millisec )
821 if ( timeout_millisec > 25000 )
824 timeout_millisec -= 25000;
828 if ( timeout_millisec < 100 )
834 ::halfdelay( timeout_millisec / 100 );
836 timeout_millisec = 0;
841 while ( got == WEOF && timeout_millisec > 0 );
848 ::nodelay( ::stdscr,
true );
852 if ( got == KEY_RESIZE )
854 NCurses::ResizeEvent();
860 got = NCDialog::getch( timeout_millisec );
862 while ( timeout_millisec < 0 && got == WEOF && --i );
869 bool NCDialog::flushTypeahead()
874 if ( eventReason == YEvent::ValueChanged ||
875 eventReason == YEvent::SelectionChanged )
877 yuiDebug() <<
"DON't flush input buffer - reason: " << eventReason << std::endl;
882 yuiDebug() <<
"Flush input buffer" << std::endl;
888 void NCDialog::idleInput()
892 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
897 yuiDebug() <<
"idle+ " <<
this << std::endl;
901 if ( flushTypeahead() )
910 yuiDebug() <<
"idle+ " <<
this << std::endl;
912 yuiDebug() <<
"idle- " <<
this << std::endl;
919 yuiDebug() <<
"poll+ " <<
this << std::endl;
923 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
924 return NCursesEvent::cancel;
932 yuiDebug() <<
this <<
" deactivate" << std::endl;
940 yuiDebug() <<
this <<
" activate" << std::endl;
946 eventReason = returnEvent.reason;
947 pendingEvent = NCursesEvent::none;
949 yuiDebug() <<
"poll- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
954 NCursesEvent NCDialog::userInput(
int timeout_millisec )
956 yuiDebug() <<
"user+ " <<
this << std::endl;
958 if ( flushTypeahead() )
965 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
966 return NCursesEvent::cancel;
969 processInput( timeout_millisec );
972 eventReason = returnEvent.reason;
973 pendingEvent = NCursesEvent::none;
975 yuiDebug() <<
"user- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
987 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1016 void NCDialog::processInput(
int timeout_millisec )
1018 yuiDebug() <<
"process+ " <<
this <<
" active " << wActive
1019 <<
" timeout_millisec " << timeout_millisec << std::endl;
1023 yuiDebug() <<
this <<
"(return pending event)" << std::endl;
1030 if ( wActive->GetState() != NC::WSactive )
1032 yuiDebug() <<
"noactive item => reactivate!" << std::endl;
1036 if ( wActive->GetState() != NC::WSactive )
1038 yuiDebug() <<
"still noactive item!" << std::endl;
1040 if ( timeout_millisec == -1 )
1042 pendingEvent = NCursesEvent::cancel;
1043 yuiDebug() << DLOC <<
this <<
"(std::set ET_CANCEL since noactive item on pollInput)" << std::endl;
1051 if ( timeout_millisec > 0 )
1053 usleep( timeout_millisec * 1000 );
1054 pendingEvent = NCursesEvent::timeout;
1065 yuiDebug() <<
"enter loop..." << std::endl;
1069 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1072 ch = getch( timeout_millisec );
1080 if ( timeout_millisec == -1 )
1081 pendingEvent = NCursesEvent::cancel;
1082 else if ( timeout_millisec > 0 )
1083 pendingEvent = NCursesEvent::timeout;
1110 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1111 NCurses::ScreenShot();
1112 yuiMilestone() <<
this << std::endl;
1113 DumpOn( yuiMilestone(),
" " );
1114 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1121 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1122 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1124 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1130 YDialogSpy::showDialogSpy();
1154 pendingEvent = getInputEvent( KEY_SLEFT );
1158 pendingEvent = getInputEvent( KEY_SRIGHT );
1170 pendingEvent = getInputEvent( ch );
1176 pendingEvent = getInputEvent( hch );
1180 pendingEvent = getHotkeyEvent( hch );
1187 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1189 pendingEvent = getHotkeyEvent( ch );
1193 pendingEvent = getInputEvent( ch );
1204 yuiDebug() <<
"process- " <<
this <<
" active " << wActive << std::endl;
1212 if ( wActive->isValid() )
1214 ret = wHandleInput( ch );
1215 ret.widget = wActive;
1224 return wActive->wHandleInput( ch );
1232 if ( wActive->isValid() )
1234 ret = wHandleHotkey( key );
1235 ret.widget = wActive;
1244 if ( key >= 0 && ActivateByKey( key ) )
1245 return wActive->wHandleHotkey( key );
1247 return NCursesEvent::none;
1251 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog * OBJ )
1254 return STREAM << *OBJ;
1256 return STREAM <<
"(NoNCDialog)";
1269 std::map<int, NCstring> NCDialog::describeFunctionKeys( )
1271 std::map<int, NCstring> fkeys;
1275 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1277 if ( w && w->hasFunctionKey() && w->isEnabled() )
1282 fkeys[ w->functionKey()] =
NCstring(w->debugLabel());
1290 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog & OBJ )
1292 STREAM << (
const NCWidget & )OBJ <<
' ' << OBJ.pan
1293 << ( OBJ.active ?
"{A " :
"{i " ) << OBJ.pendingEvent;
1295 if ( OBJ.pendingEvent )
1296 STREAM << OBJ.pendingEvent.widget;
1298 return STREAM <<
'}';
1302 bool NCDialog::getInvisible()
1304 if ( !pan || pan->
hidden() )
1315 bool NCDialog::getVisible()
1317 if ( !pan || !pan->
hidden() )
1326 pan->transparent( pan->
maxy(), 0 );
1331 pan->transparent( 0, pan->
maxx() );
1338 void NCDialog::resizeEvent()
1348 void NCDialog::showHotkeyHelp()
1351 _(
"<h1>Advanced Hotkeys:</h1>"
1352 "<p><b>Shift-F1</b> Show a list of advanced hotkeys.</p>"
1353 "<p><b>Shift-F4</b> Change color schema.</p>"
1354 "<p><b>Ctrl-\\</b> Quit the application.</p>"
1355 "<p><b>Ctrl-L</b> Refresh screen.</p>"
1356 "<p><b>Ctrl-D F1</b> Show a list of advanced hotkeys.</p>"
1357 "<p><b>Ctrl-D Shift-D</b> Dump dialog to the log file as a screen shot.</p>"
1358 "<p><b>Ctrl-D Shift-Y</b> Open YDialogSpy to see the widget hierarchy.</p>"
1359 "<p>Depending on your desktop environment some of these key combinations <br/>might not work.</p>" ),