28 #define YUILogComponent "ncurses" 29 #include <yui/YUILog.h> 32 #include "NCPopupInfo.h" 33 #include "NCMenuButton.h" 34 #include <yui/YShortcut.h> 35 #include "NCtoY2Event.h" 36 #include "YNCursesUI.h" 37 #include <yui/YDialogSpy.h> 38 #include <yui/YDialog.h> 43 static bool hiddenMenu()
45 return getenv(
"Y2NCDBG" ) != NULL;
49 NCDialog::NCDialog( YDialogType dialogType,
50 YDialogColorMode colorMode )
51 : YDialog( dialogType, colorMode )
60 yuiDebug() <<
"Constructor NCDialog(YDialogType t, YDialogColorMode c)" << std::endl;
65 NCDialog::NCDialog( YDialogType dialogType,
const wpos & at,
bool boxed )
66 : YDialog( dialogType, YDialogNormalColor )
72 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
75 yuiDebug() <<
"Constructor NCDialog(YDialogType t, const wpos & at, bool boxed)" << std::endl;
80 void NCDialog::_init()
82 NCurses::RememberDlg(
this );
88 if ( colorMode() == YDialogWarnColor )
90 mystyleset = NCstyle::WarnStyle;
92 else if ( colorMode() == YDialogInfoColor )
94 mystyleset = NCstyle::InfoStyle;
98 mystyleset = NCstyle::PopupStyle;
102 mystyleset = NCstyle::DefaultStyle;
105 dlgstyle = &NCurses::style()[mystyleset];
107 eventReason = YEvent::UnknownReason;
108 yuiDebug() <<
"+++ " <<
this << std::endl;
112 void NCDialog::_init_size()
114 defsze.H = NCurses::lines();
115 defsze.W = NCurses::cols();
116 hshaddow = vshaddow =
false;
147 NCDialog::~NCDialog()
149 NCurses::ForgetDlg(
this );
151 yuiDebug() <<
"--+START destroy " <<
this << std::endl;
153 if ( pan && !pan->
hidden() )
164 yuiDebug() <<
"---destroyed " <<
this << std::endl;
169 int NCDialog::preferredWidth()
171 if ( dialogType() == YMainDialog || ! hasChildren() )
172 return wGetDefsze().W;
178 csze =
wsze( firstChild()->preferredHeight(),
179 firstChild()->preferredWidth() );
182 csze = wsze::min( wGetDefsze(), wsze::max( csze,
wsze( 1 ) ) );
188 int NCDialog::preferredHeight()
190 if ( dialogType() == YMainDialog || ! hasChildren() )
192 return wGetDefsze().H;
199 csze =
wsze( firstChild()->preferredHeight(),
200 firstChild()->preferredWidth() );
203 csze = wsze::min( wGetDefsze(),
204 wsze::max( csze,
wsze( 1 ) ) );
210 void NCDialog::setSize(
int newwidth,
int newheight )
212 wRelocate(
wpos( 0 ),
wsze( newheight, newwidth ) );
213 yuiDebug() <<
"setSize() called: width: " << newwidth <<
" height: " << newheight << std::endl;
214 YDialog::setSize( newwidth, newheight );
218 void NCDialog::initDialog()
222 yuiDebug() <<
"setInitialSize() called!" << std::endl;
234 void NCDialog::showDialog()
236 yuiDebug() <<
"sd+ " <<
this << std::endl;
238 if ( pan && pan->
hidden() )
240 YPushButton *defaultB = YDialog::defaultButton();
244 defaultB->setKeyboardFocus();
250 DumpOn( yuiDebug(),
" " );
255 yuiMilestone() <<
"no pan" << std::endl;
260 yuiDebug() <<
"sd- " <<
this << std::endl;
264 void NCDialog::closeDialog()
266 yuiDebug() <<
"cd+ " <<
this << std::endl;
269 if ( pan && !pan->
hidden() )
273 yuiDebug() <<
this << std::endl;
276 yuiDebug() <<
"cd+ " <<
this << std::endl;
282 if ( active != newactive || ( pan && pan->
hidden() ) )
296 NCurses::SetStatusLine( describeFunctionKeys() );
298 yuiDebug() <<
this << std::endl;
317 void NCDialog::wMoveTo(
const wpos & newpos )
319 yuiDebug() << DLOC <<
this << newpos << std::endl;
323 void NCDialog::wCreate(
const wrect & newrect )
326 throw NCError(
"wCreate: already have win" );
328 wrect panrect( newrect );
334 switch ( NCurses::lines() - panrect.Sze.H )
350 switch ( NCurses::cols() - panrect.Sze.W )
367 if ( popedpos.L >= 0 )
369 if ( popedpos.L + panrect.Sze.H <= NCurses::lines() )
370 panrect.Pos.L = popedpos.L;
372 panrect.Pos.L = NCurses::lines() - panrect.Sze.H;
376 panrect.Pos.L = ( NCurses::lines() - panrect.Sze.H ) / 2;
379 if ( popedpos.C >= 0 )
381 if ( popedpos.C + panrect.Sze.W <= NCurses::cols() )
382 panrect.Pos.C = popedpos.C;
384 panrect.Pos.C = NCurses::cols() - panrect.Sze.W;
388 panrect.Pos.C = ( NCurses::cols() - panrect.Sze.W ) / 2;
391 if ( panrect.Pos.L + panrect.Sze.H < NCurses::lines() )
397 if ( panrect.Pos.C + panrect.Sze.W < NCurses::cols() )
415 panrect.Pos.L, panrect.Pos.C,
423 inparent.Sze.H, inparent.Sze.W,
424 inparent.Pos.L, inparent.Pos.C,
426 win->nodelay(
true );
428 yuiDebug() << DLOC << panrect <<
'(' << inparent <<
')' 429 <<
'[' << popedpos <<
']' << std::endl;
433 void NCDialog::wRedraw()
439 pan->
bkgdset( wStyle().getDlgBorder( active ).text );
441 if ( pan->
height() != NCurses::lines()
442 || pan->
width() != NCurses::cols() )
459 pan->
maxy() - 1, pan->
maxx(), false );
467 pan->
maxy(), pan->
maxx() - 1, false );
476 pan->transparent( pan->
maxy(), 0 );
482 pan->transparent( 0, pan->
maxx() );
488 void NCDialog::wRecoded()
492 if ( &NCurses::style()[mystyleset] != dlgstyle )
494 dlgstyle = &NCurses::style()[mystyleset];
497 pan->
bkgdset( wStyle(). getDumb().text );
505 void NCDialog::startMultipleChanges()
511 void NCDialog::doneMultipleChanges()
513 if ( inMultiDraw_i > 1 )
520 NCurses::SetStatusLine( describeFunctionKeys() );
525 void NCDialog::setStatusLine()
527 NCurses::SetStatusLine( describeFunctionKeys() );
531 void NCDialog::wUpdate(
bool forced_br )
537 && ( pan->
hidden() || inMultiDraw_i ) )
540 NCWidget::wUpdate( forced_br );
544 void NCDialog::grabActive(
NCWidget * nactive )
546 if ( wActive && wActive != static_cast<NCWidget *>(
this ) )
547 wActive->grabRelease(
this );
549 if ( nactive && nactive != static_cast<NCWidget *>(
this ) )
550 nactive->grabSet(
this );
552 const_cast<NCWidget *&
>( wActive ) = nactive;
556 void NCDialog::grabNotify(
NCWidget * mgrab )
558 if ( wActive && wActive == mgrab )
560 yuiDebug() << DLOC << mgrab <<
" active " << std::endl;
563 if ( wActive && wActive == mgrab )
569 bool NCDialog::wantFocus(
NCWidget & ngrab )
571 return Activate( ngrab );
575 void NCDialog::wDelete()
579 yuiDebug() << DLOC <<
"+++ " <<
this << std::endl;
581 yuiDebug() << DLOC <<
"--- " <<
this << std::endl;
588 NCWidget * c = ( startwith.*Direction )(
true )->Value();
590 while ( c != &startwith && ( c->GetState() != NC::WSnormal || !c->winExist() ) )
592 if ( c->GetState() == NC::WSactive )
594 yuiWarning() <<
"multiple active widgets in dialog? " 595 << startwith <<
" <-> " << c << std::endl;
596 c->SetState( NC::WSnormal );
600 c = ( c->*Direction )(
true )->Value();
619 bool NCDialog::Activate(
NCWidget & nactive )
621 if ( nactive.GetState() == NC::WSactive )
624 if ( nactive.GetState() == NC::WSnormal )
626 if ( wActive->GetState() == NC::WSactive )
627 wActive->SetState( NC::WSnormal );
631 nactive.SetState( NC::WSactive );
634 grabActive( &nactive );
643 void NCDialog::Activate( SeekDir Direction )
648 if ( Direction == 0 )
650 if ( Activate( *wActive ) )
657 Activate( GetNormal( *wActive, Direction ) );
661 void NCDialog::Activate()
667 void NCDialog::Deactivate()
669 if ( wActive->GetState() == NC::WSactive )
671 wActive->SetState( NC::WSnormal );
676 void NCDialog::ActivateNext()
682 void NCDialog::ActivatePrev()
688 bool NCDialog::ActivateByKey(
int key )
694 switch ( c->Value()->GetState() )
699 if ( c->Value()->HasHotkey( key )
700 || c->Value()->HasFunctionHotkey( key ) )
702 Activate( *c->Value() );
708 if ( c->IsDescendantOf( buddy ) )
710 yuiDebug() <<
"BUDDY ACTIVATION FOR " << c->Value() << std::endl;
711 Activate( *c->Value() );
715 yuiDebug() <<
"DROP BUDDY on " << c->Value() << std::endl;
724 if ( c->Value()->HasHotkey( key )
725 || c->Value()->HasFunctionHotkey( key ) )
727 yuiDebug() <<
"DUMB HOT KEY " << key <<
" in " << c->Value() << std::endl;
741 wint_t NCDialog::getinput()
745 if ( NCstring::terminalEncoding() ==
"UTF-8" )
747 wint_t gotwch = WEOF;
748 int ret = ::get_wch( &gotwch );
770 int gotch = ::getch();
774 if (( KEY_MIN > gotch || KEY_MAX < gotch )
779 str +=
static_cast<char>( gotch );
781 NCstring::RecodeToWchar( str, NCstring::terminalEncoding(), &to );
784 if ( gotch != (
int )got )
789 yuiDebug() <<
"Recode: " << str <<
" (encoding: " << NCstring::terminalEncoding() <<
") " 791 <<
"to wint_t: " << got << std::endl;
808 wint_t NCDialog::getch(
int timeout_millisec )
812 if ( timeout_millisec < 0 )
815 ::nodelay( ::stdscr,
false );
820 else if ( timeout_millisec )
825 if ( timeout_millisec > 25000 )
828 timeout_millisec -= 25000;
832 if ( timeout_millisec < 100 )
838 ::halfdelay( timeout_millisec / 100 );
840 timeout_millisec = 0;
845 while ( got == WEOF && timeout_millisec > 0 );
852 ::nodelay( ::stdscr,
true );
856 if ( got == KEY_RESIZE )
858 NCurses::ResizeEvent();
864 got = NCDialog::getch( timeout_millisec );
866 while ( timeout_millisec < 0 && got == WEOF && --i );
873 bool NCDialog::flushTypeahead()
878 if ( eventReason == YEvent::ValueChanged ||
879 eventReason == YEvent::SelectionChanged )
881 yuiDebug() <<
"DON't flush input buffer - reason: " << eventReason << std::endl;
886 yuiDebug() <<
"Flush input buffer" << std::endl;
892 void NCDialog::idleInput()
896 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
901 yuiDebug() <<
"idle+ " <<
this << std::endl;
905 if ( flushTypeahead() )
914 yuiDebug() <<
"idle+ " <<
this << std::endl;
916 yuiDebug() <<
"idle- " <<
this << std::endl;
923 yuiDebug() <<
"poll+ " <<
this << std::endl;
927 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
928 return NCursesEvent::cancel;
936 yuiDebug() <<
this <<
" deactivate" << std::endl;
944 yuiDebug() <<
this <<
" activate" << std::endl;
950 eventReason = returnEvent.reason;
951 pendingEvent = NCursesEvent::none;
953 yuiDebug() <<
"poll- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
958 NCursesEvent NCDialog::userInput(
int timeout_millisec )
960 yuiDebug() <<
"user+ " <<
this << std::endl;
962 if ( flushTypeahead() )
969 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
970 return NCursesEvent::cancel;
973 processInput( timeout_millisec );
976 eventReason = returnEvent.reason;
977 pendingEvent = NCursesEvent::none;
979 yuiDebug() <<
"user- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
991 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1020 void NCDialog::processInput(
int timeout_millisec )
1022 yuiDebug() <<
"process+ " <<
this <<
" active " << wActive
1023 <<
" timeout_millisec " << timeout_millisec << std::endl;
1027 yuiDebug() <<
this <<
"(return pending event)" << std::endl;
1034 if ( wActive->GetState() != NC::WSactive )
1036 yuiDebug() <<
"noactive item => reactivate!" << std::endl;
1040 if ( wActive->GetState() != NC::WSactive )
1042 yuiDebug() <<
"still noactive item!" << std::endl;
1044 if ( timeout_millisec == -1 )
1046 pendingEvent = NCursesEvent::cancel;
1047 yuiDebug() << DLOC <<
this <<
"(std::set ET_CANCEL since noactive item on pollInput)" << std::endl;
1055 if ( timeout_millisec > 0 )
1057 usleep( timeout_millisec * 1000 );
1058 pendingEvent = NCursesEvent::timeout;
1069 yuiDebug() <<
"enter loop..." << std::endl;
1073 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1076 ch = getch( timeout_millisec );
1087 yuiDebug() <<
"Keeping the pending event" << std::endl;
1092 if ( timeout_millisec == -1 )
1093 pendingEvent = NCursesEvent::cancel;
1094 else if ( timeout_millisec > 0 )
1095 pendingEvent = NCursesEvent::timeout;
1113 yuiMilestone() <<
"Asking for widget ID" << std::endl;
1122 Activate( *button );
1123 pendingEvent = getInputEvent( KEY_RETURN );
1141 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1142 NCurses::ScreenShot();
1143 yuiMilestone() <<
this << std::endl;
1144 DumpOn( yuiMilestone(),
" " );
1145 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1152 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1153 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1155 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1161 YDialogSpy::showDialogSpy();
1185 pendingEvent = getInputEvent( KEY_SLEFT );
1189 pendingEvent = getInputEvent( KEY_SRIGHT );
1201 pendingEvent = getInputEvent( ch );
1207 pendingEvent = getInputEvent( hch );
1211 pendingEvent = getHotkeyEvent( hch );
1218 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1220 pendingEvent = getHotkeyEvent( ch );
1224 pendingEvent = getInputEvent( ch );
1235 yuiDebug() <<
"process- " <<
this <<
" active " << wActive << std::endl;
1243 if ( wActive->isValid() )
1245 ret = wHandleInput( ch );
1246 ret.widget = wActive;
1255 return wActive->wHandleInput( ch );
1263 if ( wActive->isValid() )
1265 ret = wHandleHotkey( key );
1266 ret.widget = wActive;
1275 if ( key >= 0 && ActivateByKey( key ) )
1276 return wActive->wHandleHotkey( key );
1278 return NCursesEvent::none;
1282 std::ostream & operator<<( std::ostream & str,
const NCDialog * obj )
1287 return str <<
"(NoNCDialog)";
1300 std::map<int, NCstring> NCDialog::describeFunctionKeys( )
1302 std::map<int, NCstring> fkeys;
1306 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1308 if ( w && w->hasFunctionKey() && w->isEnabled() )
1313 fkeys[ w->functionKey()] =
NCstring(w->debugLabel());
1321 std::ostream & operator<<( std::ostream & str,
const NCDialog & obj )
1323 str << (
const NCWidget & )obj <<
' ' << obj.pan
1324 << ( obj.active ?
"{A " :
"{i " ) << obj.pendingEvent;
1326 if ( obj.pendingEvent )
1327 str << obj.pendingEvent.widget;
1333 bool NCDialog::getInvisible()
1335 if ( !pan || pan->
hidden() )
1346 bool NCDialog::getVisible()
1348 if ( !pan || !pan->
hidden() )
1357 pan->transparent( pan->
maxy(), 0 );
1362 pan->transparent( 0, pan->
maxx() );
1369 void NCDialog::resizeEvent()
1379 void NCDialog::showHotkeyHelp()
1381 std::string old_textdomain = textdomain( NULL );
1382 setTextdomain(
"ncurses" );
1385 _(
"<h1>Advanced Hotkeys:</h1>" 1386 "<p><b>Shift-F1</b> Show a list of advanced hotkeys.</p>" 1387 "<p><b>Shift-F4</b> Change color schema.</p>" 1388 "<p><b>Ctrl-\\</b> Quit the application.</p>" 1389 "<p><b>Ctrl-L</b> Refresh screen.</p>" 1390 "<p><b>Ctrl-D F1</b> Show a list of advanced hotkeys.</p>" 1391 "<p><b>Ctrl-D Shift-D</b> Dump dialog to the log file as a screen shot.</p>" 1392 "<p><b>Ctrl-D Shift-Y</b> Open YDialogSpy to see the widget hierarchy.</p>" 1393 "<p>Depending on your desktop environment some of these key combinations <br/>might not work.</p>" ),
1397 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.