25 #define YUILogComponent "ncurses"
26 #include <yui/YUILog.h>
29 #include "NCPopupInfo.h"
30 #include "NCMenuButton.h"
31 #include <yui/YShortcut.h>
33 #include "NCtoY2Event.h"
34 #include <yui/YDialogSpy.h>
44 static bool hiddenMenu()
46 return getenv(
"Y2NCDBG" ) != NULL;
50 NCDialog::NCDialog( YDialogType dialogType,
51 YDialogColorMode colorMode )
52 : YDialog( dialogType, colorMode )
61 yuiDebug() <<
"Constructor NCDialog(YDialogType t, YDialogColorMode c)" << std::endl;
66 NCDialog::NCDialog( YDialogType dialogType,
const wpos at,
const bool boxed )
67 : YDialog( dialogType, YDialogNormalColor )
73 , ncdopts( boxed ? POPUP : POPUP | NOBOX )
76 yuiDebug() <<
"Constructor NCDialog(YDialogType t, const wpos at, const bool boxed)" << std::endl;
81 void NCDialog::_init()
83 NCurses::RememberDlg(
this );
89 if ( colorMode() == YDialogWarnColor )
91 mystyleset = NCstyle::WarnStyle;
93 else if ( colorMode() == YDialogInfoColor )
95 mystyleset = NCstyle::InfoStyle;
99 mystyleset = NCstyle::PopupStyle;
103 mystyleset = NCstyle::DefaultStyle;
106 dlgstyle = &NCurses::style()[mystyleset];
108 eventReason = YEvent::UnknownReason;
109 yuiDebug() <<
"+++ " <<
this << std::endl;
113 void NCDialog::_init_size()
115 defsze.H = NCurses::lines();
116 defsze.W = NCurses::cols();
117 hshaddow = vshaddow =
false;
148 NCDialog::~NCDialog()
150 NCurses::ForgetDlg(
this );
152 yuiDebug() <<
"--+START destroy " <<
this << std::endl;
154 if ( pan && !pan->
hidden() )
165 yuiDebug() <<
"---destroyed " <<
this << std::endl;
170 int NCDialog::preferredWidth()
172 if ( dialogType() == YMainDialog || ! hasChildren() )
173 return wGetDefsze().W;
179 csze =
wsze( firstChild()->preferredHeight(),
180 firstChild()->preferredWidth() );
183 csze = wsze::min( wGetDefsze(), wsze::max( csze,
wsze( 1 ) ) );
189 int NCDialog::preferredHeight()
191 if ( dialogType() == YMainDialog || ! hasChildren() )
193 return wGetDefsze().H;
200 csze =
wsze( firstChild()->preferredHeight(),
201 firstChild()->preferredWidth() );
204 csze = wsze::min( wGetDefsze(),
205 wsze::max( csze,
wsze( 1 ) ) );
211 void NCDialog::setSize(
int newwidth,
int newheight )
213 wRelocate(
wpos( 0 ),
wsze( newheight, newwidth ) );
214 yuiDebug() <<
"setSize() called: width: " << newwidth <<
" height: " << newheight << std::endl;
215 YDialog::setSize( newwidth, newheight );
219 void NCDialog::initDialog()
223 yuiDebug() <<
"setInitialSize() called!" << std::endl;
235 void NCDialog::showDialog()
237 yuiDebug() <<
"sd+ " <<
this << std::endl;
239 if ( pan && pan->
hidden() )
241 YPushButton *defaultB = YDialog::defaultButton();
245 defaultB->setKeyboardFocus();
251 DumpOn( yuiDebug(),
" " );
256 yuiMilestone() <<
"no pan" << std::endl;
261 yuiDebug() <<
"sd- " <<
this << std::endl;
265 void NCDialog::closeDialog()
267 yuiDebug() <<
"cd+ " <<
this << std::endl;
270 if ( pan && !pan->
hidden() )
274 yuiDebug() <<
this << std::endl;
277 yuiDebug() <<
"cd+ " <<
this << std::endl;
283 if ( active != newactive || ( pan && pan->
hidden() ) )
297 NCurses::SetStatusLine( describeFunctionKeys() );
299 yuiDebug() <<
this << std::endl;
318 void NCDialog::wMoveTo(
const wpos & newpos )
320 yuiDebug() << DLOC <<
this << newpos << std::endl;
324 void NCDialog::wCreate(
const wrect & newrect )
327 throw NCError(
"wCreate: already have win" );
329 wrect panrect( newrect );
335 switch ( NCurses::lines() - panrect.Sze.H )
351 switch ( NCurses::cols() - panrect.Sze.W )
368 if ( popedpos.L >= 0 )
370 if ( popedpos.L + panrect.Sze.H <= NCurses::lines() )
371 panrect.Pos.L = popedpos.L;
373 panrect.Pos.L = NCurses::lines() - panrect.Sze.H;
377 panrect.Pos.L = ( NCurses::lines() - panrect.Sze.H ) / 2;
380 if ( popedpos.C >= 0 )
382 if ( popedpos.C + panrect.Sze.W <= NCurses::cols() )
383 panrect.Pos.C = popedpos.C;
385 panrect.Pos.C = NCurses::cols() - panrect.Sze.W;
389 panrect.Pos.C = ( NCurses::cols() - panrect.Sze.W ) / 2;
392 if ( panrect.Pos.L + panrect.Sze.H < NCurses::lines() )
398 if ( panrect.Pos.C + panrect.Sze.W < NCurses::cols() )
416 panrect.Pos.L, panrect.Pos.C,
424 inparent.Sze.H, inparent.Sze.W,
425 inparent.Pos.L, inparent.Pos.C,
427 win->nodelay(
true );
429 yuiDebug() << DLOC << panrect <<
'(' << inparent <<
')'
430 <<
'[' << popedpos <<
']' << std::endl;
434 void NCDialog::wRedraw()
440 pan->
bkgdset( wStyle().getDlgBorder( active ).text );
442 if ( pan->
height() != NCurses::lines()
443 || pan->
width() != NCurses::cols() )
460 pan->
maxy() - 1, pan->
maxx(), false );
468 pan->
maxy(), pan->
maxx() - 1, false );
477 pan->transparent( pan->
maxy(), 0 );
483 pan->transparent( 0, pan->
maxx() );
489 void NCDialog::wRecoded()
493 if ( &NCurses::style()[mystyleset] != dlgstyle )
495 dlgstyle = &NCurses::style()[mystyleset];
498 pan->
bkgdset( wStyle(). getDumb().text );
506 void NCDialog::startMultipleChanges()
512 void NCDialog::doneMultipleChanges()
514 if ( inMultiDraw_i > 1 )
521 NCurses::SetStatusLine( describeFunctionKeys() );
526 void NCDialog::setStatusLine()
528 NCurses::SetStatusLine( describeFunctionKeys() );
532 void NCDialog::wUpdate(
bool forced_br )
538 && ( pan->
hidden() || inMultiDraw_i ) )
541 NCWidget::wUpdate( forced_br );
545 void NCDialog::grabActive(
NCWidget * nactive )
547 if ( wActive && wActive != static_cast<NCWidget *>(
this ) )
548 wActive->grabRelease(
this );
550 if ( nactive && nactive != static_cast<NCWidget *>(
this ) )
551 nactive->grabSet(
this );
553 const_cast<NCWidget *&
>( wActive ) = nactive;
557 void NCDialog::grabNotify(
NCWidget * mgrab )
559 if ( wActive && wActive == mgrab )
561 yuiDebug() << DLOC << mgrab <<
" active " << std::endl;
564 if ( wActive && wActive == mgrab )
570 bool NCDialog::wantFocus(
NCWidget & ngrab )
572 return Activate( ngrab );
576 void NCDialog::wDelete()
580 yuiDebug() << DLOC <<
"+++ " <<
this << std::endl;
582 yuiDebug() << DLOC <<
"--- " <<
this << std::endl;
589 NCWidget * c = ( startwith.*Direction )(
true )->Value();
591 while ( c != &startwith && ( c->GetState() != NC::WSnormal || !c->winExist() ) )
593 if ( c->GetState() == NC::WSactive )
595 yuiWarning() <<
"multiple active widgets in dialog? "
596 << startwith <<
" <-> " << c << std::endl;
597 c->SetState( NC::WSnormal );
601 c = ( c->*Direction )(
true )->Value();
620 bool NCDialog::Activate(
NCWidget & nactive )
622 if ( nactive.GetState() == NC::WSactive )
625 if ( nactive.GetState() == NC::WSnormal )
627 if ( wActive->GetState() == NC::WSactive )
628 wActive->SetState( NC::WSnormal );
632 nactive.SetState( NC::WSactive );
635 grabActive( &nactive );
644 void NCDialog::Activate( SeekDir Direction )
649 if ( Direction == 0 )
651 if ( Activate( *wActive ) )
658 Activate( GetNormal( *wActive, Direction ) );
662 void NCDialog::Activate()
668 void NCDialog::Deactivate()
670 if ( wActive->GetState() == NC::WSactive )
672 wActive->SetState( NC::WSnormal );
677 void NCDialog::ActivateNext()
683 void NCDialog::ActivatePrev()
689 bool NCDialog::ActivateByKey(
int key )
695 switch ( c->Value()->GetState() )
700 if ( c->Value()->HasHotkey( key )
701 || c->Value()->HasFunctionHotkey( key ) )
703 Activate( *c->Value() );
709 if ( c->IsDescendantOf( buddy ) )
711 yuiDebug() <<
"BUDDY ACTIVATION FOR " << c->Value() << std::endl;
712 Activate( *c->Value() );
716 yuiDebug() <<
"DROP BUDDY on " << c->Value() << std::endl;
725 if ( c->Value()->HasHotkey( key )
726 || c->Value()->HasFunctionHotkey( key ) )
728 yuiDebug() <<
"DUMB HOT KEY " << key <<
" in " << c->Value() << std::endl;
742 wint_t NCDialog::getinput()
746 if ( NCstring::terminalEncoding() ==
"UTF-8" )
748 wint_t gotwch = WEOF;
749 int ret = ::get_wch( &gotwch );
771 int gotch = ::getch();
775 if (( KEY_MIN > gotch || KEY_MAX < gotch )
780 str +=
static_cast<char>( gotch );
782 NCstring::RecodeToWchar( str, NCstring::terminalEncoding(), &to );
785 if ( gotch != (
int )got )
790 yuiDebug() <<
"Recode: " << str <<
" (encoding: " << NCstring::terminalEncoding() <<
") "
792 <<
"to wint_t: " << got << std::endl;
809 wint_t NCDialog::getch(
int timeout_millisec )
813 if ( timeout_millisec < 0 )
816 ::nodelay( ::stdscr,
false );
821 else if ( timeout_millisec )
826 if ( timeout_millisec > 25000 )
829 timeout_millisec -= 25000;
833 if ( timeout_millisec < 100 )
839 ::halfdelay( timeout_millisec / 100 );
841 timeout_millisec = 0;
846 while ( got == WEOF && timeout_millisec > 0 );
853 ::nodelay( ::stdscr,
true );
857 if ( got == KEY_RESIZE )
859 NCurses::ResizeEvent();
865 got = NCDialog::getch( timeout_millisec );
867 while ( timeout_millisec < 0 && got == WEOF && --i );
874 bool NCDialog::flushTypeahead()
879 if ( eventReason == YEvent::ValueChanged ||
880 eventReason == YEvent::SelectionChanged )
882 yuiDebug() <<
"DON't flush input buffer - reason: " << eventReason << std::endl;
887 yuiDebug() <<
"Flush input buffer" << std::endl;
893 void NCDialog::idleInput()
897 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
902 yuiDebug() <<
"idle+ " <<
this << std::endl;
906 if ( flushTypeahead() )
915 yuiDebug() <<
"idle+ " <<
this << std::endl;
917 yuiDebug() <<
"idle- " <<
this << std::endl;
924 yuiDebug() <<
"poll+ " <<
this << std::endl;
928 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
929 return NCursesEvent::cancel;
937 yuiDebug() <<
this <<
" deactivate" << std::endl;
945 yuiDebug() <<
this <<
" activate" << std::endl;
951 eventReason = returnEvent.reason;
952 pendingEvent = NCursesEvent::none;
954 yuiDebug() <<
"poll- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
959 NCursesEvent NCDialog::userInput(
int timeout_millisec )
961 yuiDebug() <<
"user+ " <<
this << std::endl;
963 if ( flushTypeahead() )
970 yuiWarning() << DLOC <<
" called for uninitialized " <<
this << std::endl;
971 return NCursesEvent::cancel;
974 processInput( timeout_millisec );
977 eventReason = returnEvent.reason;
978 pendingEvent = NCursesEvent::none;
980 yuiDebug() <<
"user- " <<
this <<
'(' << returnEvent <<
')' << std::endl;
992 cevent = userInput( timeout_millisec ? timeout_millisec : -1 );
1021 void NCDialog::processInput(
int timeout_millisec )
1023 yuiDebug() <<
"process+ " <<
this <<
" active " << wActive
1024 <<
" timeout_millisec " << timeout_millisec << std::endl;
1028 yuiDebug() <<
this <<
"(return pending event)" << std::endl;
1035 if ( wActive->GetState() != NC::WSactive )
1037 yuiDebug() <<
"noactive item => reactivate!" << std::endl;
1041 if ( wActive->GetState() != NC::WSactive )
1043 yuiDebug() <<
"still noactive item!" << std::endl;
1045 if ( timeout_millisec == -1 )
1047 pendingEvent = NCursesEvent::cancel;
1048 yuiDebug() << DLOC <<
this <<
"(std::set ET_CANCEL since noactive item on pollInput)" << std::endl;
1056 if ( timeout_millisec > 0 )
1058 usleep( timeout_millisec * 1000 );
1059 pendingEvent = NCursesEvent::timeout;
1070 yuiDebug() <<
"enter loop..." << std::endl;
1074 while ( !pendingEvent.isReturnEvent() && ch != WEOF )
1077 ch = getch( timeout_millisec );
1085 if ( timeout_millisec == -1 )
1086 pendingEvent = NCursesEvent::cancel;
1087 else if ( timeout_millisec > 0 )
1088 pendingEvent = NCursesEvent::timeout;
1107 yuiMilestone() <<
"CTRL('D')-'D' DUMP+++++++++++++++++++++" << std::endl;
1108 NCurses::ScreenShot();
1109 yuiMilestone() <<
this << std::endl;
1110 DumpOn( yuiMilestone(),
" " );
1111 yuiMilestone() <<
"CTRL('D')-'D' DUMP---------------------" << std::endl;
1118 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF+++++++++++++++++++++" << std::endl;
1119 const_cast<NCstyle&
>( NCurses::style() ).changeSyle();
1121 yuiMilestone() <<
"CTRL('D')-'S' STYLEDEF---------------------" << std::endl;
1127 YDialogSpy::showDialogSpy();
1151 pendingEvent = getInputEvent( KEY_SLEFT );
1155 pendingEvent = getInputEvent( KEY_SRIGHT );
1167 pendingEvent = getInputEvent( ch );
1173 pendingEvent = getInputEvent( hch );
1177 pendingEvent = getHotkeyEvent( hch );
1184 if ( ch >= KEY_F( 1 ) && ch <= KEY_F( 24 ) )
1186 pendingEvent = getHotkeyEvent( ch );
1190 pendingEvent = getInputEvent( ch );
1201 yuiDebug() <<
"process- " <<
this <<
" active " << wActive << std::endl;
1209 if ( wActive->isValid() )
1211 ret = wHandleInput( ch );
1212 ret.widget = wActive;
1221 return wActive->wHandleInput( ch );
1229 if ( wActive->isValid() )
1231 ret = wHandleHotkey( key );
1232 ret.widget = wActive;
1241 if ( key >= 0 && ActivateByKey( key ) )
1242 return wActive->wHandleHotkey( key );
1244 return NCursesEvent::none;
1248 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog * OBJ )
1251 return STREAM << *OBJ;
1253 return STREAM <<
"(NoNCDialog)";
1266 std::map<int, std::string> NCDialog::describeFunctionKeys( )
1268 std::map<int, std::string> fkeys;
1272 YWidget * w =
dynamic_cast<YWidget *
>( c->Value() );
1274 if ( w && w->hasFunctionKey() && w->isEnabled() )
1279 fkeys[ w->functionKey()] = w->debugLabel();
1287 std::ostream & operator<<( std::ostream & STREAM,
const NCDialog & OBJ )
1289 STREAM << (
const NCWidget & )OBJ <<
' ' << OBJ.pan
1290 << ( OBJ.active ?
"{A " :
"{i " ) << OBJ.pendingEvent;
1292 if ( OBJ.pendingEvent )
1293 STREAM << OBJ.pendingEvent.widget;
1295 return STREAM <<
'}';
1299 bool NCDialog::getInvisible()
1301 if ( !pan || pan->
hidden() )
1312 bool NCDialog::getVisible()
1314 if ( !pan || !pan->
hidden() )
1323 pan->transparent( pan->
maxy(), 0 );
1328 pan->transparent( 0, pan->
maxx() );
1335 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)