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 )
65 NCDialog::NCDialog( YDialogType dialogType,
const wpos & at,
bool boxed )
66 : YDialog( dialogType, YDialogNormalColor )
72 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
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;
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 );
153 if ( pan && !pan->
hidden() )
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 ) );
214 YDialog::setSize( newwidth, newheight );
218 void NCDialog::initDialog()
234 void NCDialog::showDialog()
238 if ( pan && pan->
hidden() )
240 YPushButton *defaultB = YDialog::defaultButton();
244 defaultB->setKeyboardFocus();
250 DumpOn( yuiDebug(),
" " );
255 yuiDebug() <<
"no pan" << std::endl;
264 void NCDialog::closeDialog()
269 if ( pan && !pan->
hidden() )
282 if ( active != newactive || ( pan && pan->
hidden() ) )
296 NCurses::SetStatusLine( describeFunctionKeys() );
317 void NCDialog::wMoveTo(
const wpos & newpos )
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 );
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 )
563 if ( wActive && wActive == mgrab )
569 bool NCDialog::wantFocus(
NCWidget & ngrab )
571 return Activate( ngrab );
575 void NCDialog::wDelete()
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 ) )
711 Activate( *c->Value() );
724 if ( c->Value()->HasHotkey( key )
725 || c->Value()->HasFunctionHotkey( key ) )
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 )
807 wint_t NCDialog::getch(
int timeout_millisec )
811 if ( timeout_millisec < 0 )
814 ::nodelay( ::stdscr,
false );
819 else if ( timeout_millisec )
824 if ( timeout_millisec > 25000 )
827 timeout_millisec -= 25000;
831 if ( timeout_millisec < 100 )
837 ::halfdelay( timeout_millisec / 100 );
839 timeout_millisec = 0;
844 while ( got == WEOF && timeout_millisec > 0 );
851 ::nodelay( ::stdscr,
true );
855 if ( got == KEY_RESIZE )
857 NCurses::ResizeEvent();
863 got = NCDialog::getch( timeout_millisec );
865 while ( timeout_millisec < 0 && got == WEOF && --i );
872 bool NCDialog::flushTypeahead()
877 if ( eventReason == YEvent::ValueChanged ||
878 eventReason == YEvent::SelectionChanged )
891 void NCDialog::idleInput()
895 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
904 if ( flushTypeahead() )
926 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
927 return NCursesEvent::cancel;
949 eventReason = returnEvent.reason;
950 pendingEvent = NCursesEvent::none;
957 NCursesEvent NCDialog::userInput(
int timeout_millisec )
961 if ( flushTypeahead() )
968 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
969 return NCursesEvent::cancel;
972 processInput( timeout_millisec );
975 eventReason = returnEvent.reason;
976 pendingEvent = NCursesEvent::none;
990 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1019 void NCDialog::processInput(
int timeout_millisec )
1033 if ( wActive->GetState() != NC::WSactive )
1039 if ( wActive->GetState() != NC::WSactive )
1043 if ( timeout_millisec == -1 )
1045 pendingEvent = NCursesEvent::cancel;
1054 if ( timeout_millisec > 0 )
1056 usleep( timeout_millisec * 1000 );
1057 pendingEvent = NCursesEvent::timeout;
1072 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1075 ch = getch( timeout_millisec );
1086 yuiDebug() <<
"Keeping the pending event" << std::endl;
1091 if ( timeout_millisec == -1 )
1092 pendingEvent = NCursesEvent::cancel;
1093 else if ( timeout_millisec > 0 )
1094 pendingEvent = NCursesEvent::timeout;
1112 yuiMilestone() <<
"Asking for widget ID" << std::endl;
1121 Activate( *button );
1122 pendingEvent = getInputEvent( KEY_RETURN );
1140 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1141 NCurses::ScreenShot();
1142 yuiMilestone() <<
this << std::endl;
1143 DumpOn( yuiMilestone(),
" " );
1144 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1151 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1152 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1154 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1160 YDialogSpy::showDialogSpy();
1184 pendingEvent = getInputEvent( KEY_SLEFT );
1188 pendingEvent = getInputEvent( KEY_SRIGHT );
1200 pendingEvent = getInputEvent( ch );
1206 pendingEvent = getInputEvent( hch );
1210 pendingEvent = getHotkeyEvent( hch );
1217 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1219 pendingEvent = getHotkeyEvent( ch );
1223 pendingEvent = getInputEvent( ch );
1242 if ( wActive->isValid() )
1244 ret = wHandleInput( ch );
1245 ret.widget = wActive;
1254 return wActive->wHandleInput( ch );
1262 if ( wActive->isValid() )
1264 ret = wHandleHotkey( key );
1265 ret.widget = wActive;
1274 if ( key >= 0 && ActivateByKey( key ) )
1275 return wActive->wHandleHotkey( key );
1277 return NCursesEvent::none;
1281 std::ostream & operator<<( std::ostream & str,
const NCDialog * obj )
1286 return str <<
"(NoNCDialog)";
1299 std::map<int, NCstring> NCDialog::describeFunctionKeys()
1301 std::map<int, NCstring> fkeys;
1305 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1307 if ( w && w->hasFunctionKey() && w->isEnabled() )
1312 fkeys[ w->functionKey()] =
NCstring(w->debugLabel());
1320 std::ostream & operator<<( std::ostream & str,
const NCDialog & obj )
1322 str << (
const NCWidget & )obj <<
' ' << obj.pan
1323 << ( obj.active ?
"{A " :
"{i " ) << obj.pendingEvent;
1325 if ( obj.pendingEvent )
1326 str << obj.pendingEvent.widget;
1332 bool NCDialog::getInvisible()
1334 if ( !pan || pan->
hidden() )
1345 bool NCDialog::getVisible()
1347 if ( !pan || !pan->
hidden() )
1356 pan->transparent( pan->
maxy(), 0 );
1361 pan->transparent( 0, pan->
maxx() );
1368 void NCDialog::resizeEvent()
1378 void NCDialog::showHotkeyHelp()
1380 std::string old_textdomain = textdomain( NULL );
1381 setTextdomain(
"ncurses" );
1384 _(
"<h1>Advanced Hotkeys:</h1>"
1385 "<p><b>Shift-F1</b> Show a list of advanced hotkeys.</p>"
1386 "<p><b>Shift-F4</b> Change color schema.</p>"
1387 "<p><b>Ctrl-\\</b> Quit the application.</p>"
1388 "<p><b>Ctrl-L</b> Refresh screen.</p>"
1389 "<p><b>Ctrl-D F1</b> Show a list of advanced hotkeys.</p>"
1390 "<p><b>Ctrl-D Shift-D</b> Dump dialog to the log file as a screen shot.</p>"
1391 "<p><b>Ctrl-D Shift-Y</b> Open YDialogSpy to see the widget hierarchy.</p>"
1392 "<p>Depending on your desktop environment some of these key combinations <br/>might not work.</p>" ),
1396 setTextdomain( old_textdomain.c_str() );