libyui-ncurses
2.44.1
|
00001 /* 00002 Copyright (C) 2000-2012 Novell, Inc 00003 This library is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU Lesser General Public License as 00005 published by the Free Software Foundation; either version 2.1 of the 00006 License, or (at your option) version 3.0 of the License. This library 00007 is distributed in the hope that it will be useful, but WITHOUT ANY 00008 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00009 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00010 License for more details. You should have received a copy of the GNU 00011 Lesser General Public License along with this library; if not, write 00012 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 00013 Floor, Boston, MA 02110-1301 USA 00014 */ 00015 00016 00017 /*-/ 00018 00019 File: NCTreePad.cc 00020 00021 Author: Michael Andres <ma@suse.de> 00022 00023 /-*/ 00024 00025 #define YUILogComponent "ncurses" 00026 #include <yui/YUILog.h> 00027 #include "NCTreePad.h" 00028 00029 00030 00031 NCTreePad::NCTreePad( int lines, int cols, const NCWidget & p ) 00032 : NCPad( lines, cols, p ) 00033 , Headpad( 1, 1 ) 00034 , dirtyHead( false ) 00035 , dirtyFormat( false ) 00036 , ItemStyle( p ) 00037 , Headline( 0 ) 00038 , Items( 0 ) 00039 , visItems( 0 ) 00040 , citem( 0 ) 00041 { 00042 } 00043 00044 00045 00046 NCTreePad::~NCTreePad() 00047 { 00048 ClearTable(); 00049 } 00050 00051 00052 00053 void NCTreePad::assertLine( unsigned idx ) 00054 { 00055 if ( idx >= Lines() ) 00056 SetLines( idx + 1 ); 00057 } 00058 00059 00060 00061 void NCTreePad::SetLines( unsigned idx ) 00062 { 00063 if ( idx == Lines() ) 00064 return; 00065 00066 unsigned olines = Lines(); 00067 00068 if ( idx < Lines() ) 00069 { 00070 for ( unsigned i = idx; i < Lines(); ++i ) 00071 { 00072 delete Items[i]; 00073 } 00074 } 00075 00076 Items.resize( idx, 0 ); 00077 00078 for ( unsigned i = olines; i < Lines(); ++i ) 00079 { 00080 if ( !Items[i] ) 00081 Items[i] = new NCTableLine( 0 ); 00082 } 00083 00084 DirtyFormat(); 00085 } 00086 00087 00088 00089 void NCTreePad::SetLines( std::vector<NCTableLine*> & nItems ) 00090 { 00091 SetLines( 0 ); 00092 Items = nItems; 00093 00094 for ( unsigned i = 0; i < Lines(); ++i ) 00095 { 00096 if ( !Items[i] ) 00097 Items[i] = new NCTableLine( 0 ); 00098 } 00099 00100 DirtyFormat(); 00101 } 00102 00103 00104 00105 void NCTreePad::AddLine( unsigned idx, NCTableLine * item ) 00106 { 00107 assertLine( idx ); 00108 delete Items[idx]; 00109 Items[idx] = item ? item : new NCTableLine( 0 ); 00110 00111 DirtyFormat(); 00112 } 00113 00114 00115 00116 void NCTreePad::DelLine( unsigned idx ) 00117 { 00118 if ( idx < Lines() ) 00119 { 00120 Items[idx]->ClearLine(); 00121 DirtyFormat(); 00122 } 00123 } 00124 00125 00126 00127 const NCTableLine * NCTreePad::GetCurrentLine() const 00128 { 00129 if ( citem.L >= 0 && ( unsigned )citem.L < visLines() ) 00130 return visItems[citem.L]; 00131 00132 return 0; 00133 } 00134 00135 00136 00137 NCTableLine * NCTreePad::ModifyLine( unsigned idx ) 00138 { 00139 if ( idx < Lines() ) 00140 { 00141 DirtyFormat(); 00142 return Items[idx]; 00143 } 00144 00145 return 0; 00146 } 00147 00148 00149 00150 const NCTableLine * NCTreePad::GetLine( unsigned idx ) const 00151 { 00152 if ( idx < Lines() ) 00153 return Items[idx]; 00154 00155 return 0; 00156 } 00157 00158 00159 00160 bool NCTreePad::SetHeadline( const std::vector<NCstring> & head ) 00161 { 00162 bool hascontent = ItemStyle.SetStyleFrom( head ); 00163 DirtyFormat(); 00164 update(); 00165 return hascontent; 00166 } 00167 00168 00169 00170 void NCTreePad::Destwin( NCursesWindow * dwin ) 00171 { 00172 NCPad::Destwin( dwin ); 00173 00174 if ( destwin ) 00175 { 00176 maxspos.L = visLines() > ( unsigned )srect.Sze.H ? visLines() - srect.Sze.H : 0; 00177 } 00178 } 00179 00180 00181 00182 void NCTreePad::wRecoded() 00183 { 00184 DirtyFormat(); 00185 update(); 00186 } 00187 00188 00189 00190 wpos NCTreePad::CurPos() const 00191 { 00192 citem.C = srect.Pos.C; 00193 return citem; 00194 } 00195 00196 00197 00198 void NCTreePad::ShowItem( const NCTableLine * item ) 00199 { 00200 if ( !item ) 00201 return; 00202 00203 if ( const_cast<NCTableLine *>( item )->ChangeToVisible() || dirtyFormat ) 00204 UpdateFormat(); 00205 00206 for ( unsigned l = 0; l < visLines(); ++l ) 00207 { 00208 if ( visItems[l] == item ) 00209 { 00210 setpos( wpos( l, srect.Pos.C ) ); 00211 break; 00212 } 00213 } 00214 } 00215 00216 00217 00218 wsze NCTreePad::UpdateFormat() 00219 { 00220 dirty = true; 00221 dirtyFormat = false; 00222 visItems.clear(); 00223 ItemStyle.ResetToMinCols(); 00224 00225 for ( unsigned l = 0; l < Lines(); ++l ) 00226 { 00227 Items[l]->UpdateFormat( ItemStyle ); 00228 00229 if ( Items[l]->isVisible() ) 00230 visItems.push_back( Items[l] ); 00231 } 00232 00233 maxspos.L = visLines() > ( unsigned )srect.Sze.H ? visLines() - srect.Sze.H : 0; 00234 00235 resize( wsze( visLines(), ItemStyle.TableWidth() ) ); 00236 return wsze( visLines(), ItemStyle.TableWidth() ); 00237 } 00238 00239 00240 00241 int NCTreePad::DoRedraw() 00242 { 00243 if ( !Destwin() ) 00244 { 00245 dirty = true; 00246 return OK; 00247 } 00248 00249 if ( dirtyFormat ) 00250 UpdateFormat(); 00251 00252 bkgdset( ItemStyle.getBG() ); 00253 00254 clear(); 00255 00256 wsze lSze( 1, width() ); 00257 00258 for ( unsigned l = 0; l < visLines(); ++l ) 00259 { 00260 visItems[l]->DrawAt( *this, wrect( wpos( l, 0 ), lSze ), 00261 ItemStyle, ( l == ( unsigned )citem.L ) ); 00262 } 00263 00264 if ( Headpad.width() != width() ) 00265 Headpad.resize( 1, width() ); 00266 00267 Headpad.clear(); 00268 00269 ItemStyle.Headline().DrawAt( Headpad, wrect( wpos( 0, 0 ), lSze ), 00270 ItemStyle, false ); 00271 00272 SendHead(); 00273 00274 dirty = false; 00275 00276 return update(); 00277 } 00278 00279 00280 00281 int NCTreePad::setpos( const wpos & newpos ) 00282 { 00283 if ( !visLines() ) 00284 { 00285 if ( dirty ) 00286 return DoRedraw(); 00287 00288 return OK; 00289 } 00290 00291 if ( dirtyFormat ) 00292 UpdateFormat(); 00293 00294 // save old values 00295 int oitem = citem.L; 00296 00297 int opos = srect.Pos.C; 00298 00299 // calc new values 00300 citem.L = newpos.L < 0 ? 0 : newpos.L; 00301 00302 if (( unsigned )citem.L >= visLines() ) 00303 citem.L = visLines() - 1; 00304 00305 srect.Pos = wpos( citem.L - ( drect.Sze.H - 1 ) / 2, newpos.C ).between( 0, maxspos ); 00306 00307 if ( citem.L != oitem ) 00308 { 00309 unsigned at = 0; 00310 unsigned len = 0; 00311 00312 if ( citem.L >= 0 && visItems[citem.L] ) 00313 len = visItems[citem.L]->Hotspot( at ); 00314 else 00315 return ERR; 00316 00317 if ( len ) 00318 { 00319 if (( int )at < srect.Pos.C ) 00320 { 00321 srect.Pos.C = at; 00322 } 00323 else if (( int )( at + len - srect.Pos.C ) > drect.Sze.W ) 00324 { 00325 srect.Pos.C = ( int )at < maxspos.C ? at : maxspos.C; 00326 } 00327 } 00328 } 00329 00330 if ( dirty ) 00331 { 00332 return DoRedraw(); 00333 } 00334 00335 // adjust only 00336 if ( citem.L != oitem ) 00337 { 00338 visItems[oitem]->DrawAt( *this, wrect( wpos( oitem, 0 ), wsze( 1, width() ) ), 00339 ItemStyle, false ); 00340 } 00341 00342 visItems[citem.L]->DrawAt( *this, wrect( wpos( citem.L, 0 ), wsze( 1, width() ) ), 00343 00344 ItemStyle, true ); 00345 00346 if ( srect.Pos.C != opos ) 00347 SendHead(); 00348 00349 return update(); 00350 } 00351 00352 00353 00354 void NCTreePad::updateScrollHint() 00355 { 00356 NCPad::updateScrollHint(); 00357 } 00358 00359 00360 00361 bool NCTreePad::handleInput( wint_t key ) 00362 { 00363 bool handled = true; 00364 00365 if ( !GetCurrentLine() ) 00366 return false; 00367 00368 switch ( key ) 00369 { 00370 case KEY_UP: 00371 case KEY_PPAGE: 00372 case KEY_DOWN: 00373 case KEY_NPAGE: 00374 //handle these in compatible way with other widgets (#251180) 00375 //jump to the first/last item 00376 00377 case KEY_HOME: 00378 case KEY_END: 00379 //scroll horizontally 00380 00381 case KEY_RIGHT: 00382 case KEY_LEFT: 00383 handled = NCPad::handleInput( key ); 00384 break; 00385 00386 //use these for toggling pack/unpack the tree 00387 00388 case '+': 00389 case '-': 00390 case KEY_IC: 00391 case KEY_DC: 00392 case KEY_SPACE: 00393 // case KEY_RETURN: - see bug 67350 00394 00395 if ( visItems[citem.L]->handleInput( key ) ) 00396 { 00397 UpdateFormat(); 00398 setpos( wpos( citem.L, srect.Pos.C ) ); 00399 } 00400 00401 break; 00402 00403 default: 00404 handled = false; 00405 } 00406 00407 return handled; 00408 } 00409 00410 00411 std::ostream & operator<<( std::ostream & STREAM, const NCTreePad & OBJ ) 00412 { 00413 STREAM << "TreePad: lines " << OBJ.Lines() << std::endl; 00414 00415 for ( unsigned idx = 0; idx < OBJ.Lines(); ++idx ) 00416 { 00417 STREAM << idx << " " << *OBJ.GetLine( idx ); 00418 } 00419 00420 return STREAM; 00421 } 00422