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()
Internal open() method: Initialize what is left over to initialize after all dialog children have bee...
bool hidden() const
Return TRUE if the panel is hidden, FALSE otherwise.
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 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 maxx() const
Largest x coord in window.
int box()
Draw a box around the window with the given vertical and horizontal drawing characters.
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...
int height() const
Number of lines in this window.
void hide()
Hide the panel.
int begy() const
Line of top left corner relative to stdscr.
Helper class for translating an NCurses event to a YEvent.
int begx() const
Column of top left corner relative to stdscr.
virtual YEvent * waitForEventInternal(int timeout_millisec)
Wait for a user event.
int maxy() const
Largest y 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.