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 activate()
Activate this dialog: Make sure that it is shown as the topmost dialog of this application and that i...
virtual YEvent * pollEventInternal()
Check if a user event is pending.
virtual void openInternal()
Internal open() method: Initialize what is left over to initialize after all dialog children have bee...
virtual YEvent * waitForEventInternal(int timeout_millisec)
Wait for a user event.
Helper class for translating an NCurses event to a YEvent.
YEvent * propagate()
The reason of existence of this class: Translate the NCursesEvent to a YEvent.
bool hidden() const
Return TRUE if the panel is hidden, FALSE otherwise.
void show()
Show the panel, i.e.
void hide()
Hide the panel.
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...
int begy() const
Line of top left corner relative to stdscr.
int maxx() const
Largest x coord in window.
void bkgdset(chtype ch)
Set the background property.
int clear()
Clear the window.
int box()
Draw a box around the window with the given vertical and horizontal drawing characters.
int vline(int len, chtype ch=0)
Draw a vertical line of len characters with the given character.
int maxy() const
Largest y coord in window.
int begx() const
Column 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 width() const
Number of columns in this window.
int height() const
Number of lines in this window.
YWidget * askSendWidgetID()
Open a pop-up dialog to ask the user for a widget ID and then send it with sendWidgetID().
static YNCursesUI * ui()
Access the global Y2NCursesUI.