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>
38 static bool hiddenMenu()
40 return getenv(
"Y2NCDBG" ) != NULL;
44 NCDialog::NCDialog( YDialogType dialogType,
45 YDialogColorMode colorMode )
46 : YDialog( dialogType, colorMode )
55 yuiDebug() <<
"Constructor NCDialog(YDialogType t, YDialogColorMode c)" << std::endl;
60 NCDialog::NCDialog( YDialogType dialogType,
const wpos at,
const bool boxed )
61 : YDialog( dialogType, YDialogNormalColor )
67 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
70 yuiDebug() <<
"Constructor NCDialog(YDialogType t, const wpos at, const bool boxed)" << std::endl;
75 void NCDialog::_init()
77 NCurses::RememberDlg(
this );
83 if ( colorMode() == YDialogWarnColor )
85 mystyleset = NCstyle::WarnStyle;
87 else if ( colorMode() == YDialogInfoColor )
89 mystyleset = NCstyle::InfoStyle;
93 mystyleset = NCstyle::PopupStyle;
97 mystyleset = NCstyle::DefaultStyle;
100 dlgstyle = &NCurses::style()[mystyleset];
102 eventReason = YEvent::UnknownReason;
103 yuiDebug() <<
"+++ " <<
this << std::endl;
107 void NCDialog::_init_size()
109 defsze.H = NCurses::lines();
110 defsze.W = NCurses::cols();
111 hshaddow = vshaddow =
false;
142 NCDialog::~NCDialog()
144 NCurses::ForgetDlg(
this );
146 yuiDebug() <<
"--+START destroy " <<
this << std::endl;
148 if ( pan && !pan->
hidden() )
159 yuiDebug() <<
"---destroyed " <<
this << std::endl;
164 int NCDialog::preferredWidth()
166 if ( dialogType() == YMainDialog || ! hasChildren() )
167 return wGetDefsze().W;
173 csze =
wsze( firstChild()->preferredHeight(),
174 firstChild()->preferredWidth() );
177 csze = wsze::min( wGetDefsze(), wsze::max( csze,
wsze( 1 ) ) );
183 int NCDialog::preferredHeight()
185 if ( dialogType() == YMainDialog || ! hasChildren() )
187 return wGetDefsze().H;
194 csze =
wsze( firstChild()->preferredHeight(),
195 firstChild()->preferredWidth() );
198 csze = wsze::min( wGetDefsze(),
199 wsze::max( csze,
wsze( 1 ) ) );
205 void NCDialog::setSize(
int newwidth,
int newheight )
207 wRelocate(
wpos( 0 ),
wsze( newheight, newwidth ) );
208 yuiDebug() <<
"setSize() called: width: " << newwidth <<
" height: " << newheight << std::endl;
209 YDialog::setSize( newwidth, newheight );
213 void NCDialog::initDialog()
217 yuiDebug() <<
"setInitialSize() called!" << std::endl;
229 void NCDialog::showDialog()
231 yuiDebug() <<
"sd+ " <<
this << std::endl;
233 if ( pan && pan->
hidden() )
235 YPushButton *defaultB = YDialog::defaultButton();
239 defaultB->setKeyboardFocus();
245 DumpOn( yuiDebug(),
" " );
250 yuiMilestone() <<
"no pan" << std::endl;
255 yuiDebug() <<
"sd- " <<
this << std::endl;
259 void NCDialog::closeDialog()
261 yuiDebug() <<
"cd+ " <<
this << std::endl;
264 if ( pan && !pan->
hidden() )
268 yuiDebug() <<
this << std::endl;
271 yuiDebug() <<
"cd+ " <<
this << std::endl;
277 if ( active != newactive || ( pan && pan->
hidden() ) )
291 NCurses::SetStatusLine( describeFunctionKeys() );
293 yuiDebug() <<
this << std::endl;
312 void NCDialog::wMoveTo(
const wpos & newpos )
314 yuiDebug() << DLOC <<
this << newpos << std::endl;
318 void NCDialog::wCreate(
const wrect & newrect )
321 throw NCError(
"wCreate: already have win" );
323 wrect panrect( newrect );
329 switch ( NCurses::lines() - panrect.Sze.H )
345 switch ( NCurses::cols() - panrect.Sze.W )
362 if ( popedpos.L >= 0 )
364 if ( popedpos.L + panrect.Sze.H <= NCurses::lines() )
365 panrect.Pos.L = popedpos.L;
367 panrect.Pos.L = NCurses::lines() - panrect.Sze.H;
371 panrect.Pos.L = ( NCurses::lines() - panrect.Sze.H ) / 2;
374 if ( popedpos.C >= 0 )
376 if ( popedpos.C + panrect.Sze.W <= NCurses::cols() )
377 panrect.Pos.C = popedpos.C;
379 panrect.Pos.C = NCurses::cols() - panrect.Sze.W;
383 panrect.Pos.C = ( NCurses::cols() - panrect.Sze.W ) / 2;
386 if ( panrect.Pos.L + panrect.Sze.H < NCurses::lines() )
392 if ( panrect.Pos.C + panrect.Sze.W < NCurses::cols() )
410 panrect.Pos.L, panrect.Pos.C,
418 inparent.Sze.H, inparent.Sze.W,
419 inparent.Pos.L, inparent.Pos.C,
421 win->nodelay(
true );
423 yuiDebug() << DLOC << panrect <<
'(' << inparent <<
')'
424 <<
'[' << popedpos <<
']' << std::endl;
428 void NCDialog::wRedraw()
434 pan->
bkgdset( wStyle().getDlgBorder( active ).text );
436 if ( pan->
height() != NCurses::lines()
437 || pan->
width() != NCurses::cols() )
454 pan->
maxy() - 1, pan->
maxx(), false );
462 pan->
maxy(), pan->
maxx() - 1, false );
471 pan->transparent( pan->
maxy(), 0 );
477 pan->transparent( 0, pan->
maxx() );
483 void NCDialog::wRecoded()
487 if ( &NCurses::style()[mystyleset] != dlgstyle )
489 dlgstyle = &NCurses::style()[mystyleset];
492 pan->
bkgdset( wStyle(). getDumb().text );
500 void NCDialog::startMultipleChanges()
506 void NCDialog::doneMultipleChanges()
508 if ( inMultiDraw_i > 1 )
515 NCurses::SetStatusLine( describeFunctionKeys() );
520 void NCDialog::setStatusLine()
522 NCurses::SetStatusLine( describeFunctionKeys() );
526 void NCDialog::wUpdate(
bool forced_br )
532 && ( pan->
hidden() || inMultiDraw_i ) )
535 NCWidget::wUpdate( forced_br );
539 void NCDialog::grabActive(
NCWidget * nactive )
541 if ( wActive && wActive != static_cast<NCWidget *>(
this ) )
542 wActive->grabRelease(
this );
544 if ( nactive && nactive != static_cast<NCWidget *>(
this ) )
545 nactive->grabSet(
this );
547 const_cast<NCWidget *&
>( wActive ) = nactive;
551 void NCDialog::grabNotify(
NCWidget * mgrab )
553 if ( wActive && wActive == mgrab )
555 yuiDebug() << DLOC << mgrab <<
" active " << std::endl;
558 if ( wActive && wActive == mgrab )
564 bool NCDialog::wantFocus(
NCWidget & ngrab )
566 return Activate( ngrab );
570 void NCDialog::wDelete()
574 yuiDebug() << DLOC <<
"+++ " <<
this << std::endl;
576 yuiDebug() << DLOC <<
"--- " <<
this << std::endl;
583 NCWidget * c = ( startwith.*Direction )(
true )->Value();
585 while ( c != &startwith && ( c->GetState() != NC::WSnormal || !c->winExist() ) )
587 if ( c->GetState() == NC::WSactive )
589 yuiWarning() <<
"multiple active widgets in dialog? "
590 << startwith <<
" <-> " << c << std::endl;
591 c->SetState( NC::WSnormal );
595 c = ( c->*Direction )(
true )->Value();
614 bool NCDialog::Activate(
NCWidget & nactive )
616 if ( nactive.GetState() == NC::WSactive )
619 if ( nactive.GetState() == NC::WSnormal )
621 if ( wActive->GetState() == NC::WSactive )
622 wActive->SetState( NC::WSnormal );
626 nactive.SetState( NC::WSactive );
629 grabActive( &nactive );
638 void NCDialog::Activate( SeekDir Direction )
643 if ( Direction == 0 )
645 if ( Activate( *wActive ) )
652 Activate( GetNormal( *wActive, Direction ) );
656 void NCDialog::Activate()
662 void NCDialog::Deactivate()
664 if ( wActive->GetState() == NC::WSactive )
666 wActive->SetState( NC::WSnormal );
671 void NCDialog::ActivateNext()
677 void NCDialog::ActivatePrev()
683 bool NCDialog::ActivateByKey(
int key )
689 switch ( c->Value()->GetState() )
694 if ( c->Value()->HasHotkey( key )
695 || c->Value()->HasFunctionHotkey( key ) )
697 Activate( *c->Value() );
703 if ( c->IsDescendantOf( buddy ) )
705 yuiDebug() <<
"BUDDY ACTIVATION FOR " << c->Value() << std::endl;
706 Activate( *c->Value() );
710 yuiDebug() <<
"DROP BUDDY on " << c->Value() << std::endl;
719 if ( c->Value()->HasHotkey( key )
720 || c->Value()->HasFunctionHotkey( key ) )
722 yuiDebug() <<
"DUMB HOT KEY " << key <<
" in " << c->Value() << std::endl;
736 wint_t NCDialog::getinput()
740 if ( NCstring::terminalEncoding() ==
"UTF-8" )
742 wint_t gotwch = WEOF;
743 int ret = ::get_wch( &gotwch );
765 int gotch = ::getch();
769 if (( KEY_MIN > gotch || KEY_MAX < gotch )
774 str +=
static_cast<char>( gotch );
776 NCstring::RecodeToWchar( str, NCstring::terminalEncoding(), &to );
779 if ( gotch != (
int )got )
784 yuiDebug() <<
"Recode: " << str <<
" (encoding: " << NCstring::terminalEncoding() <<
") "
786 <<
"to wint_t: " << got << std::endl;
803 wint_t NCDialog::getch(
int timeout_millisec )
807 if ( timeout_millisec < 0 )
810 ::nodelay( ::stdscr,
false );
815 else if ( timeout_millisec )
820 if ( timeout_millisec > 25000 )
823 timeout_millisec -= 25000;
827 if ( timeout_millisec < 100 )
833 ::halfdelay( timeout_millisec / 100 );
835 timeout_millisec = 0;
840 while ( got == WEOF && timeout_millisec > 0 );
847 ::nodelay( ::stdscr,
true );
851 if ( got == KEY_RESIZE )
853 NCurses::ResizeEvent();
859 got = NCDialog::getch( timeout_millisec );
861 while ( timeout_millisec < 0 && got == WEOF && --i );
868 bool NCDialog::flushTypeahead()
873 if ( eventReason == YEvent::ValueChanged ||
874 eventReason == YEvent::SelectionChanged )
876 yuiDebug() <<
"DON't flush input buffer - reason: " << eventReason << std::endl;
881 yuiDebug() <<
"Flush input buffer" << std::endl;
887 void NCDialog::idleInput()
891 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
896 yuiDebug() <<
"idle+ " <<
this << std::endl;
900 if ( flushTypeahead() )
909 yuiDebug() <<
"idle+ " <<
this << std::endl;
911 yuiDebug() <<
"idle- " <<
this << std::endl;
918 yuiDebug() <<
"poll+ " <<
this << std::endl;
922 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
923 return NCursesEvent::cancel;
931 yuiDebug() <<
this <<
" deactivate" << std::endl;
939 yuiDebug() <<
this <<
" activate" << std::endl;
945 eventReason = returnEvent.reason;
946 pendingEvent = NCursesEvent::none;
948 yuiDebug() <<
"poll- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
953 NCursesEvent NCDialog::userInput(
int timeout_millisec )
955 yuiDebug() <<
"user+ " <<
this << std::endl;
957 if ( flushTypeahead() )
964 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
965 return NCursesEvent::cancel;
968 processInput( timeout_millisec );
971 eventReason = returnEvent.reason;
972 pendingEvent = NCursesEvent::none;
974 yuiDebug() <<
"user- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
986 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1015 void NCDialog::processInput(
int timeout_millisec )
1017 yuiDebug() <<
"process+ " <<
this <<
" active " << wActive
1018 <<
" timeout_millisec " << timeout_millisec << std::endl;
1022 yuiDebug() <<
this <<
"(return pending event)" << std::endl;
1029 if ( wActive->GetState() != NC::WSactive )
1031 yuiDebug() <<
"noactive item => reactivate!" << std::endl;
1035 if ( wActive->GetState() != NC::WSactive )
1037 yuiDebug() <<
"still noactive item!" << std::endl;
1039 if ( timeout_millisec == -1 )
1041 pendingEvent = NCursesEvent::cancel;
1042 yuiDebug() << DLOC <<
this <<
"(std::set ET_CANCEL since noactive item on pollInput)" << std::endl;
1050 if ( timeout_millisec > 0 )
1052 usleep( timeout_millisec * 1000 );
1053 pendingEvent = NCursesEvent::timeout;
1064 yuiDebug() <<
"enter loop..." << std::endl;
1068 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1071 ch = getch( timeout_millisec );
1079 if ( timeout_millisec == -1 )
1080 pendingEvent = NCursesEvent::cancel;
1081 else if ( timeout_millisec > 0 )
1082 pendingEvent = NCursesEvent::timeout;
1101 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1102 NCurses::ScreenShot();
1103 yuiMilestone() <<
this << std::endl;
1104 DumpOn( yuiMilestone(),
" " );
1105 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1112 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1113 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1115 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1121 YDialogSpy::showDialogSpy();
1145 pendingEvent = getInputEvent( KEY_SLEFT );
1149 pendingEvent = getInputEvent( KEY_SRIGHT );
1161 pendingEvent = getInputEvent( ch );
1167 pendingEvent = getInputEvent( hch );
1171 pendingEvent = getHotkeyEvent( hch );
1178 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1180 pendingEvent = getHotkeyEvent( ch );
1184 pendingEvent = getInputEvent( ch );
1195 yuiDebug() <<
"process- " <<
this <<
" active " << wActive << std::endl;
1203 if ( wActive->isValid() )
1205 ret = wHandleInput( ch );
1206 ret.widget = wActive;
1215 return wActive->wHandleInput( ch );
1223 if ( wActive->isValid() )
1225 ret = wHandleHotkey( key );
1226 ret.widget = wActive;
1235 if ( key >= 0 && ActivateByKey( key ) )
1236 return wActive->wHandleHotkey( key );
1238 return NCursesEvent::none;
1242 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog * OBJ )
1245 return STREAM << *OBJ;
1247 return STREAM <<
"(NoNCDialog)";
1260 std::map<int, NCstring> NCDialog::describeFunctionKeys( )
1262 std::map<int, NCstring> fkeys;
1266 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1268 if ( w && w->hasFunctionKey() && w->isEnabled() )
1273 fkeys[ w->functionKey()] =
NCstring(w->debugLabel());
1281 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog & OBJ )
1283 STREAM << (
const NCWidget & )OBJ <<
' ' << OBJ.pan
1284 << ( OBJ.active ?
"{A " :
"{i " ) << OBJ.pendingEvent;
1286 if ( OBJ.pendingEvent )
1287 STREAM << OBJ.pendingEvent.widget;
1289 return STREAM <<
'}';
1293 bool NCDialog::getInvisible()
1295 if ( !pan || pan->
hidden() )
1306 bool NCDialog::getVisible()
1308 if ( !pan || !pan->
hidden() )
1317 pan->transparent( pan->
maxy(), 0 );
1322 pan->transparent( 0, pan->
maxx() );
1329 void NCDialog::resizeEvent()
virtual void openInternal()
int vline(int len, chtype ch=0)
virtual YEvent * pollEventInternal()
int hline(int len, chtype ch=0)
int copywin(NCursesWindow &win, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol, bool overlay=TRUE)
virtual YEvent * waitForEventInternal(int timeout_millisec)