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>" ),
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.
int begy() const
Line of top left corner relative to stdscr.
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.