Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

RotorBrowser.h

Go to the documentation of this file.
00001 #ifndef Impala_Visualization_RotorBrowser_RotorBrowser_h
00002 #define Impala_Visualization_RotorBrowser_RotorBrowser_h
00004 //345678901234567890123456789012345678901234567890123456789012345678901234567890
00005 // First Author: Ork
00006 // RvB: Clean-up, introduction of (multiple) keybindings, and consolidation.
00007 //
00008 // RvB: NOTE STILL UNDER CONSIDERATION:
00009 // Now the key is first offered to the "standard keys" handler, which
00010 // deals with actions valid for all modes.
00011 //
00012 // After having implemented keybindings, I still have to decide if it
00013 // would not be better, to first offer keys to the mode specific key-handlers
00014 // and, when not consumed, offer it to the "standard keys" handler.
00015 // This way the user could overrule a standard key for a specific mode,
00016 // but could also inadvertently do this.
00017 /*
00018 Default keybindings, which can be overruled in an .ini file:
00019 #########################################################################
00020 #                           ROTORBROWSER KEYBINDINGS
00021 # NOTE: If needed, with cmd option "RbKeybindingPrefix" you can add a
00022 #       prefix to the RotorBrowser keybinding cmd options, as in:
00023 #       RbKeybindingPrefix          My
00024 #       MyStdToggleShowBookmarks    b
00025 #       MyStdShowHelp-2             ?
00026 #
00027 # Below are the default keybindings for the RotorBrowser and its modes:
00028 #
00029 #########################################################################
00030 # Default: no prefix
00031 #RbKeybindingPrefix
00032 #########################################################################
00033 ## RotorBrowserStandard keybindings for all browser modes
00034 #StdToggleShowBookmarks              b
00035 #StdStopAutoStills                   esc
00036 #StdToggleAutoStills                 \t
00037 #StdToggleVideoStream                1
00038 #StdTogglePlayUntilEnd               2
00039 #StdIncrAutoStillSpeed               =
00040 #StdDecrAutoStillSpeed               -
00041 #StdIncrAnimationSpeed               ]
00042 #StdDecrAnimationSpeed               [
00043 #StdToggleShowHelp                   h
00044 #StdToggleShowHelp-1                 H
00045 #StdCrossBrowserMode                 fn5
00046 #StdRotorBrowserMode                 fn6
00047 #StdForkBrowserMode                  fn7
00048 #StdToggleShotSwallow                `
00049 #StdToggleShotSwallowThread          ~
00050 #StdToggleKeepCenterCentered         .
00051 #StdToggleKeepCenterCentered-1       l
00052 #StdBookmarkCenterPositive           space
00053 #StdBookmarkCenterNegative           x
00054 #StdBookmarkCenterNegative-1         X
00055 #StdClusterSelect                    f
00056 #StdClusterSelect-1                  F
00057 #StdClearViewedCache                 O
00058 #StdJudgeBrowseMode                  ctrl-shift#l
00059 #StdToggleAutoSelectNegatives        L
00060 
00061 ##############################################################################
00062 #### RotorBrowserClusterSelector keybindings
00063 #CsNextPage                          d
00064 #CsNextPage-1                        D
00065 #CsPrevPage                          a
00066 #CsPrevPage-1                        A
00067 #CsIncrSelectionSize                 w
00068 #CsIncrSelectionSize-1               W
00069 #CsDecrSelectionSize                 s
00070 #CsDecrSelectionSize-1               S
00071 #CsBrowseDecrSelectionSize           a
00072 #CsBrowseDecrSelectionSize-1         A
00073 #CsBrowseIncrSelectionSize           d
00074 #CsBrowseIncrSelectionSize-1         D
00075 #CsTogglePaginate                    r
00076 #CsTogglePaginate-1                  R
00077 #CsBookPositive                      space
00078 #CsBookPositiveForced                shift#space
00079 #CsBookNegative                      x
00080 #CsBookNegativeForced                X
00081 
00082 ######################################################
00083 ### Visual Query
00084 #VisualQuery_vissemgabor             V
00085 #VisualQuery_vissem                  B
00086 #VisualQuery_fusionvissemgabor       N
00087 #VisualQuery_labhistogram            M
00088 
00089 ######################################################
00090 ### RotorBrowser (RotorbrowserMode) keybindings
00091 #RbGoForward                         d
00092 #RbGoBackward                        a
00093 #RbGoFirst                           q
00094 #RbGoLast                            e
00095 #RbBookmarkNext                      D // based on centerCentered
00096 #RbBookmarkPrev                      A // based on centerCentered
00097 #RbSwitchToContextNext               w
00098 #RbSwitchToContextPrev               W
00099 #RbSwitchToContextTime               t
00100 #RbSwitchToContextBookmark           T
00101 #RbReturnLastInitialQuery            r
00102 #RbReturnLastInitialQuery-1          R
00103 #RbToggleShowRankThreads             o
00104 
00105 #######################################################
00106 ### CrossBrowser keybindings
00107 #CbGoFirst                           q
00108 #CbGoLast                            e
00109 #CbGoInitialQuery                    r
00110 #CbGoInitialQuery-1                  R
00111 #CbGoUp                              w
00112 #CbGoUp-1                            up
00113 #CbGoDown                            s
00114 #CbGoDown-1                          down
00115 #CbGoLeft                            a
00116 #CbGoLeft-1                          left
00117 #CbGoRight                           d
00118 #CbGoRight-1                         right
00119 
00120 #CbBookmarkPrevNegative              ctrl#a                       
00121 #CbBookmarkPrevNegative-1            ctrl#left
00122 #CbBookmarkNextNegative              ctrl#d                       
00123 #CbBookmarkNextNegative-1            ctrl#right
00124 #CbBookmarkPrevPositive              A                       
00125 #CbBookmarkPrevPositive-1            shift#left                       
00126 #CbBookmarkNextPositive              D                       
00127 #CbBookmarkNextPositive-1            shift#right
00128 
00129 #CbBookmarkUpNegative                ctrl#w                       
00130 #CbBookmarkUpNegative-1              ctrl#up
00131 #CbBookmarkDownNegative              ctrl#s                       
00132 #CbBookmarkDownNegative-1            ctrl#down
00133 #CbBookmarkUpPositive                W                       
00134 #CbBookmarkUpPositive-1              shift#up                       
00135 #CbBookmarkDownPositive              S                       
00136 #CbBookmarkDownPositive-1            shift#down
00137 
00138 #CbBookmarkUpNegative                ctrl#w                       
00139 #CbBookmarkUpNegative-1              ctrl#up
00140 #CbBookmarkDownNegative              ctrl#s                       
00141 #CbBookmarkDownNegative-1            ctrl#down
00142 #CbBookmarkUpPositive                W                       
00143 #CbBookmarkUpPositive-1              shift#up                       
00144 #CbBookmarkDownPositive              S                       
00145 #CbBookmarkDownPositive-1            shift#down
00146 
00147 #FbTimeBackward                      a
00148 #FbTimeBackward-1                    left
00149 #FbTimeForward                       d
00150 #FbTimeForward-1                     right
00151 
00152 #FbBookmarkPositiveTimeBackward      A
00153 #FbBookmarkPositiveTimeBackward-1    shift#left
00154 #FbBookmarkPositiveTimeForward       D
00155 #FbBookmarkPositiveTimeForward-1     shift#right
00156 
00157 #FbBookmarkNegativeTimeBackward      ctrl#a
00158 #FbBookmarkNegativeTimeBackward-1    ctrl#left
00159 #FbBookmarkNegativeTimeForward       ctrl#d
00160 #FbBookmarkNegativeTimeForward-1     ctrl#right
00161 
00162 #FbLastHistory                       s
00163 #FbLastHistory-1                     down
00164 #FbBookmarkPositiveHistoryGoLast     S
00165 #FbBookmarkPositiveHistoryGoLast-1   shift#down
00166 #FbBookmarkNegativeHistoryGoLast     ctrl#s
00167 #FbBookmarkNegativeHistoryGoLast-1   ctrl#down
00168 
00169 #FbLastQueryShot                     r
00170 #FbQueryForward                      w   
00171 #FbQueryForward-1                    up   
00172 #FbBookmarkPositiveQueryForward      W
00173 #FbBookmarkPositiveQueryForward-1    shift#up
00174 #FbBookmarkNegativeQueryForward      ctrl#w
00175 #FbBookmarkNegativeQueryForward-1    ctrl#up
00176 
00177 #FbGaborForward                      e
00178 #FbBookmarkPositiveGaborForward      E
00179 #FbBookmarkNegativeGaborForward      ctrl#e
00180 
00181 #FbVissemForward                     q
00182 #FbBookmarkPositiveVissemForward     Q
00183 #FbBookmarkNegativeVissemForward     ctrl#q
00184 ###############################################################################
00185 ## End of RotorBrowser keybindings
00186 ###############################################################################
00187 */
00188 #include <list>
00189 
00190 //#include "OglGui/Window.h"
00191 #include "RotorBrowserListener.h"
00192 #include "RotorView.h"
00193 #include "RotorBrowserContext.h"
00194 #include "ThreadClusterSelector.h"
00195 
00196 #include "Visualization/KeyBindingsMap.h"
00197 #include "Visualization/GUI/HelpViewer.h"
00198 #include "Visualization/StatusOverlayWindow.h"
00199 #include "Visualization/FontHandler.h"
00200 #include "Visualization/VideoMinimap.h"
00201 
00202 #include "Core/VideoSet/SegmentationDocument.h"
00203 #include "Core/Trec/VisualQueryEngine.h"
00204 #include "Core/Trec/ThreadSet.h"
00205 #include "Core/Table/TableTem.h"
00206 #include "Core/Table/Sort.h"
00207 
00208 #include "Sandbox/ork/ProgramNameReader.h"
00209 #include "Basis/CmdOptions.h"
00210 
00211 namespace Impala {
00212 namespace Visualization {
00213 namespace RotorBrowser {
00214 
00215 typedef Core::Table::TableTem
00216         <Core::Column::ColumnTem<Int32>,
00217         Core::Column::ColumnTem<Core::Trec::Thread*> >     TableThreadWidthId;
00218 
00219 class RotorBrowser : public OglGui::Window, public RotorViewListener
00220 {
00221 public:
00222     typedef std::list<RotorBrowserContext*>         RotorBrowserContextList;
00223     typedef std::list<RotorView*>                   RotorViewList;
00224     typedef Core::Array::Element::Vec3Int32         Vec3Int32;
00225     typedef Core::Trec::VisualQueryEngine           VisualQueryEngine;
00226     typedef Core::Trec::ThreadSet                   ThreadSet;
00227     typedef Core::Trec::Thread                      Thread;
00228     typedef Core::Trec::ThreadBookmarked            ThreadBookmarked;
00229     typedef Core::Trec::ThreadHistory               ThreadHistory;
00230     typedef Core::Trec::ThreadVirtual               ThreadVirtual;
00231     typedef Core::Trec::ThreadVisualSimilarity      ThreadVisualSimilarity;
00232     typedef Core::Trec::KeyframeResult              KeyframeResult;
00233     typedef Core::VideoSet::SegmentationDocument    SegmentationDocument;
00234     typedef Core::VideoSet::Stills                  Stills;
00235     typedef Core::ImageSet::ImageSet                ImageSet;
00236 
00237     RotorBrowser(OglGui::Window *parent, int w, int h, ThreadSet *threadset,
00238                  SegmentationDocument *document, String preFix = "") :
00239         OglGui::Window(parent, w, h, false)
00240     {
00241         Init(threadset, document, preFix);
00242     }
00243 
00244     RotorBrowser(OglGui::Window *parent, int x, int y, int w, int h,
00245                  ThreadSet *threadset, SegmentationDocument *document,
00246                  String preFix = "") :
00247         OglGui::Window(parent, x, y, w, h, false)
00248     {
00249         Init(threadset, document, preFix);
00250     }
00251 
00252     ~RotorBrowser()
00253     {
00254         ILOG_DEBUG("~RotorBrowser()");
00255         delete mActiveContext;
00256     }
00257 
00258     void SetRotorBrowserListener(RotorBrowserListener *listener)
00259     {
00260         mRotorBrowserListener = listener;
00261     }
00262 
00263     bool CheckKBN(String keyStr, int c, int state, int n=6)
00264     {
00265         keyStr = mPreFix + keyStr;
00266         return CheckKeyBindingExt(mKeyBindings, keyStr, c, state, n);
00267     }
00268 
00269     RotorBrowserContext*    GetActiveContext() { return mActiveContext; }
00270     RotorBrowserContextList GetOtherContexts() { return mContexts; }
00271 
00272     int  GetBrowseMode()                { return mBrowseMode; }
00273     bool GetKeepCenterCentered()        { return mKeepCenterCentered; }
00274     void SetShowDirection(bool sd)      { mShowDirection = sd; }
00275     bool GetShowDirection()             { return mShowDirection; }
00276     void SetActiveHorizontal(bool ah)   { mActiveHorizontal = ah; }
00277     bool GetActiveHorizontal()          { return mActiveHorizontal; }
00278     void SetManageContexts(bool mc)     { mManageContexts = mc; }
00279     bool GetManageContexts()            { return mManageContexts; }
00280     void SetTopNRelevant(int topn)      { mTopN = topn; }
00281     int  GetTopNRelevant()              { return mTopN; }
00282     void SetMinimapEnabled(bool val)    { mMinimapEnabled = val; }
00283     bool GetMinimapEnabled()            { return mMinimapEnabled; }
00284     int  GetNrActiveContexts()          { return mContexts.size() + 1; }
00285     bool GetEnableShotSwallow()         { return mEnableShotSwallow; }
00286 
00287     void SetProgramNames(Samples::ProgramNameReader *programs)
00288     {
00289         mPrograms = programs;
00290     }
00291 
00292     void SetBrowseMode(int mode)
00293     {
00294         ILOG_SYSTEM("RotorBrowser SetBrowseMode to " << mode);
00295         mBrowseMode = mode;
00296         CheckFocus(true);
00297 
00298         if (mBrowseMode == MODE_CROSSBROWSER)
00299         {
00300             InitCrossBrowser();
00301             ShowStatusStr("Current Browser", "CrossBrowser", oglDARKGREY);
00302         }
00303         if (mBrowseMode == MODE_ROTORBROWSER)
00304         {
00305             InitRotorBrowser();
00306             ShowStatusStr("Current Browser", "RotorBrowser", 0xffcccc22);
00307         }
00308         if (mBrowseMode == MODE_FORKBROWSER)
00309         {
00310             InitForkBrowser();
00311             ShowStatusStr("Current Browser", "ForkBrowser", 0xff2222cc);
00312         }
00313         UpdateViewsToContext();
00314     }
00315 
00316     // RvB: Experimental
00317     RotorView* GetCenterRotorView()
00318     {
00319         if (!mActiveContext)
00320             return 0;
00321         return mCache->FindViewFor(mActiveContext->GetName(),
00322                                    mActiveContext->GetCenter());
00323     }
00324 
00325     void EnableCenterVideoStills(bool mode)
00326     {
00327         if (mAutoStills==STILLS_NONE)
00328             mode = false;
00329         RotorView* rotorView = GetCenterRotorView();
00330         if (!rotorView)
00331             return;
00332         if (mode)
00333         {
00334             const int curFileId = mDocument->CurFileId();
00335             if (curFileId != mDisabledCenterVideo)
00336             {
00337                 mDisabledCenterVideo = 
00338                     rotorView->EnableVideoStills(mDocument) ? -1 : curFileId;
00339                 if (mDisabledCenterVideo == -1)
00340                     return;
00341             }
00342         }
00343         rotorView->DisableVideoStills();
00344     }
00345 
00346     virtual void InitFunc()
00347     {
00348         OglGui::Window::InitFunc();
00349         view3DSys.SetCamera(GetOGLWND(),0.0f,0.0f,+4.0f,0.0f,0.0f,0.0f);
00350     }
00351 
00352     virtual void DisplayFunc()
00353     {
00354 // RvB: Added as screen sometimes flashes when using Widgets otherwise
00355 #ifndef AS_TODS_BROWSER
00356         CheckFocus();
00357 #endif
00358         view3DSys.View3DCameraTransform(GetOGLWND());
00359 
00360         // 29-8-2007 -Ork- place name of current time thread on horizontal axis:
00361         if (mBrowseMode==MODE_CROSSBROWSER || mBrowseMode==MODE_FORKBROWSER)
00362         {
00363             RotorBrowserContext *time = GetContext("time");
00364             float w = 1.0 + time->GetDepth() * 2.0;
00365             Printf3D(w/3,-1.05f,-9.1f,0.4f,0.4f,0.1f,time->GetNiceName());
00366         }
00367 
00368         if (mBrowseMode == MODE_ROTORBROWSER)
00369         {
00370             RotorBrowserContextList::iterator ctx;
00371             for (ctx = mContexts.begin(); ctx != mContexts.end(); ctx++)
00372             {
00373                 glPushMatrix();
00374                 float w = 1.0 + (*ctx)->GetDepth() * 3.0;
00375                 glRotatef((*ctx)->GetDirection()/M_PI*180.0f,0.f,0.f,1.f);
00376                 Printf3D(w/3,-1.05f,-9.1f,0.4f,0.4f,0.1f,(*ctx)->GetNiceName());
00377                 glPopMatrix();
00378             }
00379         }
00380         
00381         if (mBrowseMode == MODE_ROTORBROWSER && mShowDirection)
00382         {
00383             glPushMatrix();
00384             float w = 1.0 + mActiveContext->GetDepth() * 3.0;
00385             OGC   oldOGC;
00386             INT   oldBlendInfo[3];
00387             OGCSave(&oldOGC);
00388             oglSys.StartBlend(&oldBlendInfo[0]);
00389             glRotatef(mActiveContext->GetDirection()/M_PI*180.f, 0.f, 0.f, 1.f);
00390             ULONG colL = 0x22ff0000, colR = 0x2200ff00;
00391             SetFillColors(colL,colR,colR,colL,0xee000000);
00392             FillRoundRectExt3D(-w/2, -1.f, -10.1f, w, 2.f, 5.f, 5.f, 5.f, 5.f);
00393             glColor3f(0.5f, 0.f, 0.f);
00394             Printf3D(w/4, -1.f, -8.1f, 0.5f, 0.5f, 0.1f,
00395                      mActiveContext->GetNiceName());
00396             oglSys.EndBlend(&oldBlendInfo[0]);
00397             OGCRestore(&oldOGC);
00398             glPopMatrix();
00399         }
00400 
00401         if (mBrowseMode == MODE_FORKBROWSER)
00402         {
00403             // FORK_TODO
00404         }
00405 
00406         // retrieve the active views (in a nice OGLy fashion):
00407         RotorViewList views = mCache->GetViews();
00408 
00409         // show them all:
00410         bool updateNeeded = false;
00411         RotorViewList::const_iterator i;
00412         for (i = views.begin(); i != views.end(); i++)
00413             updateNeeded |= (*i)->DrawView();
00414 
00415         if (updateNeeded)
00416             UpdateScene();
00417     }
00418 
00419 
00420     virtual void KeyboardFunc(int c, int state)
00421     {
00422         bool keySwallowed = false;
00423         StopStills();
00424 //RvB: Rather than passing keys to Window::KeyboardFunc only when not swallowed
00425 //SetDisableOGLViewKeys(true) should be called in Init(), and here should call:
00426 //OglGui::Window::KeyboardFunc(c,state);
00427         if (!keySwallowed && mClusterSelector->IsActive())
00428             keySwallowed = KeyboardClusterSelectionFunc(c, state);
00429 
00430         if (!keySwallowed)
00431             keySwallowed = StdKeyboardFunc(c,state);
00432 
00433         if (!keySwallowed)
00434         {
00435             if (mBrowseMode == MODE_ROTORBROWSER)
00436                 keySwallowed = KeyboardRotorFunc(c, state);
00437             if (mBrowseMode == MODE_CROSSBROWSER)
00438                 keySwallowed = KeyboardCrossFunc(c, state);
00439             if (mBrowseMode == MODE_FORKBROWSER)
00440                 keySwallowed = KeyboardForkFunc(c, state);
00441         }
00442 
00443         if (!keySwallowed)
00444         {
00445             ILOG_DEBUG("key "<<c<<" state "<<state<<" still unswallowed." );
00446             Window::KeyboardFunc(c, state);
00447         }
00448         StartStills();
00449         UpdateScene(true);
00450     }
00451 
00452     bool StdKeyboardFunc(int c, int state)
00453     {
00454         bool keyHandled = true;
00455         bool book;
00456 
00457         if (CheckKBN("StdToggleShowBookmarks", c, state))
00458         {
00459             ILOG_USER("KB: show/hide bookmarks thread");
00460             DoShowBookmarksThread();
00461         }
00462         else if (CheckKBN("StdStopAutoStills", c, state))
00463         {
00464             ILOG_USER("KB: Stop autostill feature");
00465             StopAutoStills();
00466             ShowStatusStr("Shot still player", false);
00467         }
00468         else if (CheckKBN("StdToggleAutoStills", c, state))
00469         {
00470             ILOG_USER("KB: Toggle autostill feature");
00471             ToggleAutoStills();
00472         }
00473         else if (CheckKBN("StdToggleVideoStream", c, state))
00474         {
00475             ILOG_USER( "KB: toggling video stream for center shot" );
00476             ToggleEnableVideoStream();
00477         }
00478         else if (CheckKBN("StdTogglePlayUntilEnd", c, state))
00479         {
00480             ILOG_USER("KB: toggling video continuous to end for center shot");
00481             TogglePlayUntilEnd();
00482         }
00483         else if (CheckKBN("StdIncrAutoStillSpeed", c, state))
00484         {
00485             int va = RotorView::GetStillFrameWait();
00486             va -= 2;
00487             if (va < 1) va = 1;
00488             mStatusOverlay->ShowStatus("Stills animation delay", va, 1, 40);
00489             ILOG_USER( "KB: autostills faster, now " << va );
00490             RotorView::SetStillFrameWait(va);
00491         }
00492         else if (CheckKBN("StdDecrAutoStillSpeed", c, state))
00493         {
00494             int va = RotorView::GetStillFrameWait();
00495             va += 2;
00496             if (va > 40) va = 40;
00497             mStatusOverlay->ShowStatus("Stills animation delay", va, 1, 40);
00498             ILOG_USER( "KB: autostills slower, now " << va );
00499             RotorView::SetStillFrameWait(va);
00500         }
00501         else if (CheckKBN("StdIncrAnimationSpeed", c, state))
00502         {
00503             ILOG_USER( "KB: DEBUG: increase sFactor" );
00504             RotorView::SetSpeedFactor( RotorView::GetSpeedFactor() + 0.8 );
00505             mStatusOverlay->ShowStatus("Animation delay",
00506                                        RotorView::GetSpeedFactor(), 1, 20);
00507         }
00508         else if (CheckKBN("StdDecrAnimationSpeed", c, state))
00509         {
00510             ILOG_USER( "KB: DEBUG: decrease sFactor" );
00511             RotorView::SetSpeedFactor( RotorView::GetSpeedFactor() - 0.8 );
00512             mStatusOverlay->ShowStatus("Animation delay",
00513                                        RotorView::GetSpeedFactor(), 1, 20);
00514         }
00515         else if (CheckKBN("StdToggleShowHelp", c, state))
00516         {
00517             ILOG_USER( "KB: Toggle display inline help viewer" );
00518             mHelpViewer->SetVisible(!mHelpViewer->GetVisible());
00519         }
00520         else if (CheckKBN("StdCrossBrowserMode", c, state))
00521         {
00522             ILOG_USER( "KB: switch browser to CrossBrowser" );
00523             SetBrowseMode(RotorBrowser::MODE_CROSSBROWSER);
00524         }
00525 #ifndef AS_TODS_BROWSER
00526         else if (CheckKBN("StdRotorBrowserMode", c, state))
00527         {
00528             ILOG_USER( "KB: switch browser to RotorBrowser" );
00529             SetBrowseMode(RotorBrowser::MODE_ROTORBROWSER);
00530         }
00531         else if (CheckKBN("StdForkBrowserMode", c, state))
00532         {
00533             ILOG_USER("KB: switch browser to ForkBrowser");
00534             SetBrowseMode(RotorBrowser::MODE_FORKBROWSER);
00535         }
00536 #endif
00537         else if (CheckKBN("StdToggleShotSwallow", c, state))
00538         {
00539             SetEnableShotSwallow(!GetEnableShotSwallow());
00540             ILOG_USER("KB: toggle enable shot swallow. Now " <<
00541                       GetEnableShotSwallow());
00542             UpdateViewsToContext();
00543         }
00544         else if (CheckKBN("StdToggleShotSwallowThread", c, state))
00545         {
00546             ToggleShotSwallowThread();
00547             ILOG_USER("KB: toggle shot swallow thread.");
00548             UpdateViewsToContext();
00549         }
00550         else if (CheckKBN("StdToggleKeepCenterCentered", c, state))
00551         {
00552             SetKeepCenterCentered(!GetKeepCenterCentered());
00553             ILOG_USER("KB: toggle keep center shot centered. Now " <<
00554                       GetKeepCenterCentered() );
00555             UpdateViewsToContext();
00556         }            
00557         else if ((book=CheckKBN("StdBookmarkCenterPositive", c, state)) ||
00558                  CheckKBN("StdBookmarkCenterNegative", c, state))
00559         {
00560             ILOG_USER("KB: " << (book ? "bookmark" : "remove") << " center " <<
00561                       mActiveContext->GetCenter() << " from " <<
00562                       mActiveContext->GetName());
00563             BookmarkActiveCenterEx(c==' ');
00564             UpdateViewsToContext();
00565         }
00566 #ifndef AS_TODS_BROWSER
00567         else if (CheckKBN("StdClusterSelect", c, state))
00568         {
00569             ILOG_USER("KB: cluster select in active thread direction");
00570             ClusterSelect();
00571             UpdateViewsToContext();
00572         }
00573 #endif
00574         else if (CheckKBN("StdClearViewedCache", c, state))
00575         {
00576             ILOG_USER("KB: (debug code) reset viewed shots");
00577             ClearViewedCache();
00578             UpdateViewsToContext();
00579         }
00580         else if (CheckKBN("StdJudgeBrowseMode", c, state))
00581         {
00582             ILOG_USER("KB: (debug code) activating judge-browse mode.");
00583             RotorBrowserContext::SetAutoNegatives(false);
00584             RotorView::SetShowNegativeBookmarks(true);
00585             RotorView::SetShowProbabilityFeedback(false);
00586             ClearViewedCache();
00587             UpdateViewsToContext();
00588         }
00589         else if (CheckKBN("StdToggleAutoSelectNegatives", c, state))
00590         {
00591             bool nstate = !RotorBrowserContext::GetAutoNegatives();
00592             ILOG_USER("KB: (debug code) toggle auto-select negatives. " <<
00593                       "Now " << nstate);
00594             RotorBrowserContext::SetAutoNegatives(nstate);
00595             RotorView::SetShowNegativeBookmarks(nstate);
00596             RotorView::SetShowProbabilityFeedback(nstate);
00597             if (!nstate)
00598                 ClearViewedCache();
00599             UpdateViewsToContext();
00600         }
00601         else
00602             keyHandled = false;
00603         return keyHandled;
00604     }
00605 
00606     // handle keyboard interaction for cluster selector, return true
00607     // when key was handled.
00608     bool KeyboardClusterSelectionFunc(int c, int state)
00609     {
00610         if (mClusterSelector->ClusterKeyboardFunc(c,state))
00611             return true;
00612 
00613         bool force    = false;
00614         bool positive = false;
00615 
00616         if ((positive = CheckKBN("CsBookPositive", c, state)) ||
00617             (force = positive = CheckKBN("CsBookPositiveForce", c, state)) ||
00618             (CheckKBN("CsBookNegative", c, state)) ||
00619             (force = CheckKBN("CsBookNegativeForce", c, state)))
00620         {
00621             ILOG_USER("KB: " << (force ? "force" : "") <<
00622                       "bookmark cluster viewer selection " <<
00623                       (positive ? "" : "as negative"));
00624             DoBookmarkCluster(positive, force);
00625             return true;
00626         }
00627         return false;
00628     }
00629 
00630     bool CrossBrowserNavigateKey(int c, int state, bool keepCenter)
00631     {
00632         int up=0, down=0, left=0, right=0;
00633 
00634         if ((up    = CheckKBN("CbGoUp",    c, state)) ||
00635             (down  = CheckKBN("CbGoDown",  c, state)) ||
00636             (left  = CheckKBN("CbGoLeft",  c, state)) ||
00637             (right = CheckKBN("CbGoRight", c, state)))
00638         {
00639             state = 0; // Only move
00640         }
00641         else if ((up   = CheckKBN("CbBookmarkUpNegative",   c, state)) ||
00642                  (down = CheckKBN("CbBookmarkDownNegative", c, state)) ||
00643                  (left = CheckKBN("CbBookmarkPrevNegative", c, state)) ||
00644                  (right= CheckKBN("CbBookmarkNextNegative", c, state)))
00645         {
00646             state = oglControl; // Bookmark negative
00647         }
00648         else if ((up   = CheckKBN("CbBookmarkUpPositive",   c, state)) ||
00649                  (down = CheckKBN("CbBookmarkDownPositive", c, state)) ||
00650                  (left = CheckKBN("CbBookmarkPrevPositive", c, state)) ||
00651                  (right= CheckKBN("CbBookmarkNextPositive", c, state)))
00652         {
00653             state = oglShift; // Bookmark positive
00654         }
00655         if (up)    c = oglUP;
00656         if (down)  c = oglDOWN;
00657         if (left)  c = oglLEFT;
00658         if (right) c = oglRIGHT;
00659 
00660         if (!(left || right || up || down))
00661             return false;
00662 
00663         char*  dirStr[] = {"UP (forward)", "DOWN (backward)", "LEFT", "RIGHT"};
00664         String action   = (state==oglControl) ? " removing " : " bookmarking ";
00665 
00666         if (!keepCenter && (state==oglShift || state==oglControl))
00667         {
00668             BookmarkActiveCenterEx(state==oglShift);
00669             ILOG_USER("KB: " << action << " center "  <<
00670                       mActiveContext->GetCenter() << " from " <<
00671                       mActiveContext->GetName() << " and....");
00672         }
00673 
00674         SwitchToContext((left||right) ? "time" : "shots_initialquery");
00675 
00676         if (keepCenter && (state == oglControl || state == oglShift))
00677         {
00678             int dir     = (left || up) ? -1 : 1;
00679             int target  = mActiveContext->GetRelative(dir);
00680 
00681             BookmarkSpecificEx(target, state==oglShift);
00682             ILOG_USER("KB: " << action << dirStr[c-oglUP] << target);
00683             UpdateViewsToContext();
00684         }
00685 
00686         if (!keepCenter)
00687         {
00688             ILOG_USER("KB: crossbrowser " << dirStr[c-oglUP]);
00689             if (left || down)
00690                 mActiveContext->GoLeft();
00691             if (right || up)
00692                 mActiveContext->GoRight();
00693             UpdateViewsToContext();
00694             PublishContextMoved((left || down) ? -1 : 1);
00695         }
00696         return true;
00697     }
00698 
00699     bool VisualQueryKey(int c, int state)
00700     {
00701         String visStr = "";
00702         if (CheckKBN("VisualQuery_vissemgabor", c, state))
00703             visStr = "vissemgabor";
00704         if (CheckKBN("VisualQuery_vissem", c, state))
00705             visStr = "vissem";
00706         if (CheckKBN("VisualQuery_fusionvissemgabor", c, state))
00707             visStr = "fusionvissemgabor";
00708         if (CheckKBN("VisualQuery_labhistogram", c, state))
00709             visStr = "labhistogram";
00710 
00711         if (!visStr.empty())
00712         {
00713             int center = mActiveContext->GetCenter();
00714             if (mBrowseMode==MODE_CROSSBROWSER)
00715                 ILOG_USER("KB: CrossBrowser switching initialquery to " <<
00716                           visStr << " for active " << center);
00717             if (mBrowseMode==MODE_ROTORBROWSER)
00718                 ILOG_USER("KB: RotorBrowser generate visual " << visStr <<
00719                           " thread for active " << center);
00720             DoVisualQuery(visStr);
00721             return true;
00722         }
00723         return false;
00724     }
00725 
00726     bool KeyboardCrossFunc(int c, int state)
00727     {
00728         if (CrossBrowserNavigateKey(c,state,mKeepCenterCentered))
00729             return true;
00730 
00731         if (VisualQueryKey(c,state))
00732             return true;
00733 
00734         // other CrossBrowser keys:
00735         bool    keyHandled  = true;
00736 
00737         if (CheckKBN("CbGoFirst", c, state))
00738         {
00739             ILOG_USER( "KB: CrossBrowser moving to FIRST" );
00740             ResetRanking();
00741         }
00742         if (CheckKBN("CbGoLast", c, state))
00743         {
00744             ILOG_USER( "KB: CrossBrowser moving to LAST" );
00745             SwitchToContext("shots_initialquery");
00746             mActiveContext->GoLast();
00747             UpdateViewsToContext();
00748             PublishContextMoved(1);
00749         }
00750         if (CheckKBN("CbGoInitialQuery", c, state))
00751         {
00752             ILOG_USER("KB: Return to original search query");
00753             DoReturnToFirstQuery();
00754         }
00755         else
00756             keyHandled = false;
00757 
00758         return keyHandled;
00759     }
00760 
00761     bool RotorBrowserNavigateKey(int k, int state, bool keepCenter)
00762     {
00763         int c = 0;
00764         if ( CheckKBN("RbGoForward", k, state))
00765             c = 'd';
00766         else if (CheckKBN("RbGoBackward", k, state))
00767             c = 'a';
00768         else if (CheckKBN("RbGoFirst", k, state))
00769             c = 'q';
00770         else if (CheckKBN("RbGoLast", k, state))
00771             c = 'e';
00772         else if (CheckKBN("RbBookmarkNext", k, state))
00773             c = 'D';
00774         else if (CheckKBN("RbBookmarkPrev", k, state))
00775             c = 'A';
00776 
00777         if (!c)
00778             return false;
00779 
00780         if (c=='a') mActiveContext->GoLeft();
00781         if (c=='d') mActiveContext->GoRight();
00782         if (c=='q') mActiveContext->GoFirst();
00783         if (c=='e') mActiveContext->GoLast();
00784 
00785         if (c=='q' || c=='e')
00786             ILOG_USER("KB: RotorBrowser moving active " <<
00787                       mActiveContext->GetName() << " to " <<
00788                       (c=='q' ? "FIRST" : "LAST"));
00789 
00790 
00791         if (c=='A' || c=='D')
00792         {
00793             if (!mKeepCenterCentered) {
00794                 ILOG_USER("KB: bookmark center " <<
00795                            mActiveContext->GetCenter()  << " from " <<
00796                            mActiveContext->GetName() << " and go " <<
00797                            (c=='A' ? "LEFT" : "RIGHT") << " in "<<
00798                            mActiveContext->GetName());
00799                 int nextshot = mActiveContext->GetRelative(c=='A'? -1 : 1);
00800                 BookmarkActiveCenter();
00801                 mActiveContext->GoTo(nextshot);
00802             }
00803             else
00804             {
00805                 int target = mActiveContext->GetRelative(c=='A' ? -1 : 1);
00806                 ILOG_USER("KB: RotorBrowser bookmark " << target <<
00807                           (c=='A'? "left" : "right") << " of center from " <<
00808                           mActiveContext->GetName() );
00809                 BookmarkSpecific(target);
00810             }
00811         }
00812         UpdateViewsToContext();
00813         if ( !(keepCenter && (c=='A' || c=='D')))
00814             PublishContextMoved((c=='A' || c=='a' || c=='q') ? -1 : 1);
00815 
00816         return true;
00817     }
00818 
00819     bool KeyboardRotorFunc(int c, int state)
00820     {
00821         if (VisualQueryKey(c,state))
00822             return true;
00823 
00824         if (RotorBrowserNavigateKey(c,state,mKeepCenterCentered))
00825             return true;
00826 
00827         bool keySwallowed = true;
00828         if (CheckKBN("RbSwitchToContextNext", c, state))
00829         {
00830             ILOG_USER( "KB: RotorBrowser switch to NEXT context" );
00831             SwitchToNextContext();
00832             UpdateViewsToContext();
00833         }
00834         else if (CheckKBN("RbSwitchToContextPrev", c, state))
00835         {
00836             ILOG_USER( "KB: RotorBrowser switch to PREVIOUS context" );
00837             SwitchToPreviousContext();
00838             UpdateViewsToContext();
00839         }
00840         else if (CheckKBN("RbSwitchToContextTime", c, state))
00841         {
00842             ILOG_USER( "KB: RotorBrowser switch to context 'time'" );
00843             SwitchToContext("time");
00844             UpdateViewsToContext();
00845         }
00846         else if (CheckKBN("RbSwitchToContextBookmark", c, state))
00847         {
00848             ILOG_USER( "KB: RotorBrowser switch to context 'bookmarked'" );
00849             if (!HasContext("bookmarked"))
00850             {
00851                 Thread* t = GetThreadByName("bookmarked");
00852                 mContexts.push_back(new RotorBrowserContext(mCache,t,0,0.0f,4));
00853             }
00854             SwitchToContext("bookmarked");
00855             UpdateViewsToContext();
00856         }
00857         else if (CheckKBN("RbReturnLastInitialQuery", c, state))
00858         {
00859             ILOG_USER("KB: return to last known initialquery position " <<
00860                       mInitialQueryPosition );
00861             SwitchToContext("shots_initialquery");
00862             if (mActiveContext->GetName() == "shots_initialquery")
00863             {
00864                 ILOG_DEBUG("current context = initialquery" );
00865                 mActiveContext->GoTo(mInitialQueryPosition);
00866                 ILOG_DEBUG("current context = " << mActiveContext->GetCenter());
00867                 UpdateViewsToContext();
00868             }
00869             else
00870                 ILOG_DEBUG("return to context failed, current context=" <<
00871                            mActiveContext->GetName() );
00872         }
00873         else if (CheckKBN("RbToggleShowRankThreads", c, state))
00874         {
00875             ILOG_USER( "KB: toggling show rank threads" );
00876             mShowRankThreads = !mShowRankThreads;
00877             ShowStatusStr("Show extra threads", mShowRankThreads);
00878             UpdateViewsToContext();
00879         }
00880         else
00881             keySwallowed = false;
00882 
00883         return keySwallowed;
00884     }
00885 
00886     void KbBookmarkActiveCenter(bool positive)
00887     {
00888         ILOG_USER("KB: bookmarking center " << mActiveContext->GetCenter() <<
00889                   " from " << mActiveContext->GetName() << " and....");
00890         if (positive)
00891             BookmarkActiveCenter();
00892         else
00893             BookmarkActiveCenterNegative();
00894     }
00895 
00896     void KbNavigateFork(char* str, int dir, char* logStr )
00897     {
00898         ILOG_USER("KB: ForkBrowser " << logStr);
00899         SwitchToContext(str);
00900         if (dir == -1)
00901             mActiveContext->GoLeft();
00902         if (dir == 1)
00903             mActiveContext->GoRight();
00904         AddCenterToHistory();
00905         if (!strcmp(str,"shots_initialquery"))
00906             mForkLastQueryShot = mActiveContext->GetCenter();
00907         UpdateViewsToContext();
00908         PublishContextMoved(dir);
00909     }
00910 
00911     bool KeyboardForkFunc(int c, int state)
00912     {
00913         int l = 0, r = 0, v = 0, g = 0, q = 0, h = 0;
00914 
00915         if (
00916             (l = CheckKBN("FbBookmarkPositiveTimeBackward",  c, state)) ||
00917             (r = CheckKBN("FbBookmarkPositiveTimeForward",   c, state)) ||
00918             (v = CheckKBN("FbBookmarkPositiveVissemForward", c, state)) ||
00919             (g = CheckKBN("FbBookmarkPositiveGaborForward",  c, state)) ||
00920             (q = CheckKBN("FbBookmarkPositiveQueryForward",  c, state)) ||
00921             (h = CheckKBN("FbBookmarkPositiveHistoryGoLast", c, state)))
00922         {
00923             KbBookmarkActiveCenter(true);
00924         }
00925         else if (
00926             (l = CheckKBN("FbBookmarkNegativeTimeBackward",  c, state)) ||
00927             (r = CheckKBN("FbBookmarkNegativeTimeForward",   c, state)) ||
00928             (v = CheckKBN("FbBookmarkNegativeVissemForward", c, state)) ||
00929             (g = CheckKBN("FbBookmarkNegativeGaborForward",  c, state)) ||
00930             (q = CheckKBN("FbBookmarkNegativeQueryForward",  c, state)) ||
00931             (h = CheckKBN("FbBookmarkNegativeHistoryGoLast", c, state)))
00932         {
00933             KbBookmarkActiveCenter(false);
00934         }
00935         else if (
00936             (l = CheckKBN("FbTimeBackward",  c, state)) ||
00937             (r = CheckKBN("FbTimeForward",   c, state)) ||
00938             (v = CheckKBN("FbVissemForward", c, state)) ||
00939             (g = CheckKBN("FbGaborForward",  c, state)) ||
00940             (q = CheckKBN("FbQueryForward",  c, state)) ||
00941             (h = CheckKBN("FbLastHistory",   c, state)))
00942         {}
00943     
00944         bool keySwallowed = true;
00945         if (l)
00946             KbNavigateFork("time",-1,"LEFT in TIME");
00947         else if (r)
00948             KbNavigateFork("time",1,"RIGHT in TIME");
00949         else if (g)
00950             KbNavigateFork("visual_vissemgabor",1,"NEXT in visually similar");
00951         else if (v)
00952             KbNavigateFork("visual_vissem",1,"NEXT in conceptually similar");
00953         else if (q)
00954             KbNavigateFork("shots_initialquery",1,"NEXT in QUERY");
00955         else if (h)
00956         {
00957             ILOG_USER( "KB: ForkBrowser LAST in HISTORY" );
00958             SwitchToContext("history");
00959             mActiveContext->GoLeft();
00960             UpdateViewsToContext();
00961             PublishContextMoved(-1);
00962         }
00963         else if (CheckKBN("FbLastQueryShot", c, state))
00964         {
00965             ILOG_USER("KB: ForkBrowser return to last shot selected from QUERY "
00966                       << mForkLastQueryShot);
00967             // DoReturnToFirstQuery();
00968             if (mForkLastQueryShot > -1)
00969             {
00970                 SwitchToContext("shots_initialquery");
00971                 mActiveContext->GoTo(mForkLastQueryShot);
00972                 AddCenterToHistory();
00973                 UpdateViewsToContext();
00974             }
00975         }
00976         else
00977             keySwallowed = false;
00978         return keySwallowed;
00979     }
00980 
00981     void PublishContextMoved(int dir)
00982     {
00983         if (!mRotorBrowserListener || !mActiveContext)
00984             return;
00985         int center = mActiveContext->GetCenter();
00986         mRotorBrowserListener->ContextMoveEvent(this, dir, center);
00987     }
00988 
00989     void AddCenterToHistory()
00990     {
00991         if (mActiveContext != 0)
00992             AddToHistory(mActiveContext->GetCenter());
00993     }
00994 
00995     void AddToHistory(int shot)
00996     {
00997         ThreadHistory *history = (ThreadHistory*)GetThreadByName("history");
00998         if (history != 0)
00999         {
01000             history->Remove(shot);
01001             history->Push(shot);
01002             if (mTrailHistory)
01003                 mTrailHistory->Push(shot);
01004         }
01005     }
01006 
01007     virtual void MouseFunc(int msg, int but, int state, int x, int y)
01008     {
01009         if (msg == oglMouseWheelUp)
01010         {
01011             KeyboardFunc('s', state);
01012             return;
01013         }
01014 
01015         if (msg == oglMouseWheelDown)
01016         {
01017             KeyboardFunc('w', state);
01018             return;
01019         }
01020 
01021         if ((state & oglAlt) || (msg != oglMouseDown))
01022         {
01023 #ifndef AS_TODS_BROWSER
01024             Window::MouseFunc(msg, but, state, x, y);
01025 #endif
01026             return;
01027         }
01028         OGLVIEW3D *v = view3DSys.FindView(mOglWnd, x, y);
01029         if (v == NULL) return;
01030         RotorView *view = RotorViewCache::OGLVIEW3DToRotorView(v);
01031         if (view == NULL) return;
01032 
01033         if (but == oglLeftButton)
01034         {
01035             if (state & oglShift)
01036             {
01037                 // move to the clicked shot.
01038                 int vNr = view->GetNR();
01039                 RotorBrowserContext *c = FindContextForPosition(vNr);
01040                 if (!c) return;
01041 
01042                 ILOG_USER("MOUSE: move to shot " << vNr <<
01043                           " from context " << c->GetName() );
01044                 if (SwitchToContext(c->GetName()))
01045                 {
01046                     mActiveContext->GoTo(vNr);
01047                     UpdateViewsToContext();
01048                     PublishContextMoved(0);
01049                 }
01050             }
01051             else
01052             {
01053                 ILOG_USER("MOUSE: click on shot " << view->GetNR() <<
01054                           " at " << view->GetName());
01055                 BookmarkSpecific(view->GetNR());
01056                 view->UpdateBookmarkState();
01057                 if (mBrowseMode == MODE_FORKBROWSER)
01058                 {
01059                     AddToHistory(view->GetNR());
01060                     UpdateViewsToContext();
01061                 }
01062             }
01063         }
01064         if (but == oglRightButton)
01065         {
01066             ILOG_USER("MOUSE: rightclick on shot " << view->GetNR() <<
01067                       " at " << view->GetName() );
01068             BookmarkSpecificNegative(view->GetNR());
01069             view->UpdateBookmarkState();
01070         }
01071     }
01072 
01073     void AddContext(Thread *thread, int initialpos, float direction=0.0f,
01074                     int depth=3)
01075     {
01076         if (HasContext(thread->GetName()))
01077         {
01078             ILOG_DEBUG("RotorBrowser::AddContext(" << thread->GetName() <<
01079                        "): already exists. not added." );
01080             return;
01081         }
01082         ILOG_DEBUG("RotorBrowser::AddContext(" << thread->GetName() <<
01083                    ", " << initialpos <<")" );
01084 
01085         if (thread->GetName() == "shots_initialquery")
01086             mInitialQueryPosition = -1;
01087 
01088         RotorBrowserContext *add =
01089             new RotorBrowserContext(mCache,thread,initialpos,direction,depth);
01090         add->SetSwallowThread(GetThreadByName("virtual_hidden"));
01091         add->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
01092         mContexts.push_back(add);
01093 
01094         RepositionContexts();
01095         UpdateViewsToContext();
01096     }
01097 
01098     void ReloadCrossBrowser(int position = -1)
01099     {
01100         ILOG_DEBUG( "ReloadCrossBrowser()" );
01101         SwitchToContext("shots_initialquery");
01102         if (mActiveContext->GetName() != "shots_initialquery")
01103         {
01104             ILOG_WARN("active context is not initialquery. " << 
01105                       "Aborting ReloadCrossBrowser." );
01106             return;
01107         }
01108         delete mActiveContext;
01109         mActiveContext = NULL;
01110         InitCrossBrowser(position);
01111         UpdateViewsToContext();
01112     }
01113 
01114     // RvB: Was never used. Now used by SetInitialQueryToMovies
01115     void ReloadForkBrowser()
01116     {
01117         ILOG_DEBUG("ReloadForkBrowser()");
01118         SwitchToContext("shots_initialquery");
01119         if (mActiveContext->GetName() != "shots_initialquery")
01120         {
01121             ILOG_WARN("active context is not initialquery. " << 
01122                       "Aborting ReloadForkBrowser." );
01123             return;
01124         }
01125         delete mActiveContext;
01126         mActiveContext = NULL;
01127         InitForkBrowser();
01128         UpdateViewsToContext();
01129         
01130         // FORK_TODO
01131     }
01132 
01133     void ReloadInitial()
01134     {
01135         if (mClusterSelector->IsActive())
01136         {
01137             ILOG_DEBUG("hiding cluster selector");
01138             mClusterSelector->Hide();
01139         }
01140 
01141         ClearTrails();
01142 
01143         if (mBrowseMode==MODE_CROSSBROWSER || mBrowseMode==MODE_FORKBROWSER)
01144         {
01145             UpdateViewsToContext();
01146             return;
01147         }
01148 
01149         ILOG_SYSTEM( "reloading initial query" );
01150         if (!mActiveContext || mActiveContext->GetName()!="shots_initalquery")
01151         {
01152             ILOG_DEBUG( "initialquery was not active, activating..." );
01153             SwitchToContext("shots_initialquery");
01154         }
01155         if (mActiveContext && mActiveContext->GetName()=="shots_initialquery")
01156         {
01157             delete mActiveContext;
01158             mActiveContext = NULL;
01159             SwitchToContext("time");
01160             UpdateViewsToContext();
01161             SwitchToContext("shots_initialquery");
01162         }
01163     }
01164 
01165     void ResetRanking()
01166     {
01167         SwitchToContext("shots_initialquery");
01168         mActiveContext->GoFirst();
01169         UpdateViewsToContext();
01170         PublishContextMoved(-1);
01171     }
01172 
01173     void RemoveContext(String name)
01174     {
01175         if (mActiveContext->GetName() == name)
01176         {
01177             if (mContexts.size() < 1)
01178             {
01179                 ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01180                            "): is active and alone. Not removed.");
01181                 return;
01182             }
01183             SwitchToNextContext();
01184         }
01185         RotorBrowserContextList::iterator context;
01186         for (context=mContexts.begin(); context!=mContexts.end(); context++)
01187             if ((*context)->GetName() == name)
01188                 break;
01189         
01190         if (context != mContexts.end())
01191         {
01192             delete *context;
01193             mContexts.erase(context);
01194             ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01195                        "): erased. " << mContexts.size() <<
01196                        " contexts remaining.");
01197         }
01198         else
01199             ILOG_DEBUG("RotorBrowser::RemoveContext(" << name <<
01200                        "): was not in active contexts. " );
01201 
01202         RepositionContexts();
01203         UpdateViewsToContext();
01204     }
01205 
01206     void SetEnableShotSwallow(bool swallow)
01207     {
01208         if (mKeepCenterCentered)
01209         {
01210             ShowStatusStr("Bookmarked shots", "hidden, keep center enabled",
01211                           0xffdddd22);
01212             return;
01213         }
01214         mEnableShotSwallow = swallow;
01215         RotorBrowserContext::SetGlobalShotSwallow(swallow);
01216         if (swallow)
01217             ShowStatusStr("Bookmarked shots", "hidden", oglDARKRED);
01218         else
01219             ShowStatusStr("Bookmarked shots", "shown", oglDARKGREEN);
01220     }
01221 
01222     void ToggleShotSwallowThread()
01223     {
01224         ThreadVirtual *v = (ThreadVirtual*)GetThreadByName("virtual_hidden");
01225         Thread *positive = GetThreadByName("bookmarked");
01226         Thread *negative = GetThreadByName("bookmarked_negative");
01227 
01228         SetEnableShotSwallow(true);
01229         // RvB: No check was made on v
01230         if (!v)
01231             return;
01232         if (v->HasThread(positive) && v->HasThread(negative))
01233         {
01234             v->RemoveThread(positive);
01235             ShowStatusStr("Hide shots", "only negative", oglDARKRED);
01236             return;
01237         }
01238         if (v->HasThread(negative))
01239         {
01240             v->RemoveThread(negative); 
01241             v->AddThread(positive);
01242             ShowStatusStr("Hide shots", "only positive", oglDARKGREEN);
01243             return;
01244         }
01245         if (v->HasThread(positive)) {
01246             v->AddThread(negative);
01247             ShowStatusStr("Hide shots","both positive and negative",0xffdddd22);
01248             return;
01249         }
01250     }
01251 
01252     void SetKeepCenterCentered(bool centercentered)
01253     {
01254         if (mBrowseMode==MODE_FORKBROWSER)
01255         {
01256             ShowStatusStr("Center shot stays in center",
01257                           "N/A in ForkBrowser mode", 0xffdddd22);
01258             return;
01259         }
01260         mKeepCenterCentered = centercentered;
01261         ShowStatusStr("Center Shot stays in center", mKeepCenterCentered);
01262 
01263         // keep center centered func will only work with shot swallow enabled.
01264         if (mKeepCenterCentered)
01265         {
01266             RotorBrowserContext::SetGlobalShotSwallow(true);
01267             if (mActiveContext) // HACK! Should not be required.
01268                 mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
01269         }
01270         else
01271             RotorBrowserContext::SetGlobalShotSwallow(mEnableShotSwallow);
01272     }
01273 
01274     /*
01275         UpdateViewsToContext
01276             manage the active RotorView objects, and match them to the active
01277             RotorBrowserContext objects.
01278     */
01279     void UpdateViewsToContext()
01280     {
01281         if (mBusyManaging)
01282             return;
01283 
01284         if (mClusterSelector->IsActive())
01285         {
01286             // the cluster selector does not use RotorBrowserContext objects,
01287             // but uses it's own View manager, so we do not use this manager.
01288             return;
01289         }
01290         if (mManageContexts)
01291             ManageContexts();
01292 
01293         RotorBrowserContext* time;
01294         if (mPrograms && (time = GetContext("time")))
01295         {
01296             String shotTitle = mPrograms->GetTitleForShot(time->GetCenter());
01297             time->SetNiceName("time: " + shotTitle);
01298         }
01299 
01300         int cPos = mActiveContext->GetCenter();
01301         if (mActiveContext->GetName() == "shots_initialquery")
01302             mInitialQueryPosition = cPos;
01303         mCache->DoHide(mCache->GetViews());
01304         mActiveContext->UpdateViewsToContext();
01305         if (cPos >= 0)
01306         {
01307             // set document to current position:
01308             mDocument->GotoKeyfr(mThreadSet->GetKeyframes()->GetShotRKF(cPos));
01309             UpdateTrails(); // update map:
01310             if (mTrailVisited)
01311                 mTrailVisited->Push(cPos);
01312         }
01313 
01314         RotorBrowserContextList::const_iterator context;
01315 
01316         RotorBrowserContext *matchcontext;
01317 
01318         /* Context updating is dependent on the type of browser: */
01319         if (mBrowseMode == MODE_ROTORBROWSER)
01320         {
01321             matchcontext = mActiveContext;
01322             for (context=mContexts.begin(); context!=mContexts.end(); context++)
01323                 (*context)->UpdateViewsToContext(matchcontext);
01324         }
01325         else if (mBrowseMode == MODE_CROSSBROWSER)
01326         {
01327             matchcontext = GetContext("shots_initialquery");
01328             for (context=mContexts.begin(); context!=mContexts.end(); context++)
01329                 (*context)->UpdateViewsToContext(matchcontext);
01330         }
01331         else if (mBrowseMode == MODE_FORKBROWSER)
01332             UpdateForkContexts();
01333 
01334         mCache->DoCleanup(mCache->GetViews());
01335 
01336         UpdateViewedShotBookmarks();
01337     }
01338 
01339     void UpdateForkContexts()
01340     {
01341 
01342         // add the visual and conceptual similarity directions,
01343         Thread* visual = GetThreadByName("visual_vissemgabor");
01344         ((ThreadVisualSimilarity*)visual)->SetMaxReturned(100);
01345 
01346         Thread* conceptual = GetThreadByName("visual_vissem");
01347         ((ThreadVisualSimilarity*)conceptual)->SetMaxReturned(100);
01348 
01349         if (mTrailVisibleVisualA && mTrailVisibleVisualB)
01350         {
01351             mTrailVisibleVisualA->AddThread(visual, 9);
01352             mTrailVisibleVisualB->AddThread(conceptual, 9);
01353         }
01354 
01355         // update each thread according to fork browsing:
01356         RotorBrowserContextList::const_iterator context;
01357         for (context = mContexts.begin(); context != mContexts.end(); context++)
01358         {
01359             if ((*context)->GetName() == "shots_initialquery")
01360                 (*context)->UpdateViewsToContext(*context);
01361             else if ((*context)->GetName() == "history")
01362             {
01363                 // if history is not active always show the last entry:
01364                 (*context)->GoLast();
01365                 (*context)->UpdateViewsToContext(*context);
01366             }
01367             else
01368                 (*context)->UpdateViewsToContext(mActiveContext);
01369         }
01370     }
01371 
01372     void Redraw()
01373     {
01374         UpdateViewsToContext();
01375     }
01376 
01377     /* register the shot trails generated by RotorBrowser with any minimap
01378        object, so that they appear in that minimap
01379     */
01380     void RegisterShotTrails(VideoMinimap *map)
01381     {
01382         mTrailBookmarks =
01383             new ShotTrail("bookmarks", 1000, Vec3Int32(0,128,0), 0.0);
01384         mTrailVisibleTime =
01385             new ShotTrail("visible_time", 20, Vec3Int32(0,255,0), 0.05);
01386         mTrailVisibleQuery =
01387             new ShotTrail("visible_query", 100, Vec3Int32(255,0,255), 0.01);
01388         mTrailVisibleVisualA =
01389             new ShotTrail("visible_visualA", 10, Vec3Int32(255,255,0), 0.1);
01390         mTrailVisibleVisualB =
01391             new ShotTrail("visible_visualB", 10, Vec3Int32(255,255,0), 0.1);
01392         mTrailVisited =
01393             new ShotTrail("visited", 80000, Vec3Int32(64,64,64), 0.001);
01394         mTrailHistory =
01395             new ShotTrail("history", 100, Vec3Int32(255, 0, 0), 0.01);
01396         map->RegisterTrail(mTrailVisited);
01397         map->RegisterTrail(mTrailVisibleTime);
01398         map->RegisterTrail(mTrailVisibleVisualA);
01399         map->RegisterTrail(mTrailVisibleVisualB);
01400         map->RegisterTrail(mTrailVisibleQuery);
01401         map->RegisterTrail(mTrailHistory);
01402         map->RegisterTrail(mTrailBookmarks);
01403         mMinimapEnabled = true;
01404     }
01405 
01406     void ClearTrails()
01407     {
01408         ClearVisibleTrails();
01409         if (mTrailBookmarks)
01410             mTrailBookmarks->Clear();
01411         if (mTrailHistory)
01412             mTrailHistory->Clear();
01413         if (mTrailVisited)
01414             mTrailVisited->Clear();
01415     }
01416 
01417     void ClearVisibleTrails()
01418     {
01419         if (mTrailVisibleVisualA)
01420             mTrailVisibleVisualA->Clear();
01421         if (mTrailVisibleVisualB)
01422             mTrailVisibleVisualB->Clear();
01423         if (mTrailVisibleTime)
01424             mTrailVisibleTime->Clear();
01425         if (mTrailVisibleQuery)
01426             mTrailVisibleQuery->Clear();
01427     }
01428 
01429     void UpdateTrails()
01430     {
01431         if (!mMinimapEnabled)
01432             return;
01433 
01434         // clear current trails:
01435         ClearVisibleTrails();
01436 
01437         String cName = mActiveContext->GetName();
01438         // search through actives:
01439         if (mTrailVisibleQuery && cName == "shots_initialquery")
01440             mTrailVisibleQuery->AddBrowserContext(mActiveContext, 100);
01441 
01442         if (mTrailVisibleTime && cName == "time")
01443             mTrailVisibleTime->AddBrowserContext(mActiveContext, 20, true);
01444 
01445         // search through other contexts:
01446         RotorBrowserContextList::iterator context;
01447         for (context = mContexts.begin(); context != mContexts.end(); context++)
01448         {
01449             if ((*context)->GetName() == "shots_initialquery")
01450             {
01451                 if (mTrailVisibleQuery)
01452                     mTrailVisibleQuery->AddBrowserContext(*context, 100);
01453             }
01454             else if ((*context)->GetName() == "time")
01455             {
01456                 if (mTrailVisibleTime)
01457                     mTrailVisibleTime->AddBrowserContext(*context, 20, true);
01458             }
01459         }
01460     }
01461 
01462     void ClearViewedCache()
01463     {
01464         mCache->ClearShotViewed();
01465     }
01466 
01467     bool ShotHasBeenDumpedByTrecvidAtTheLastMinute(int shotid)
01468     {
01469     switch (mThreadSet->GetSegmentation()->GetVideoId(shotid))
01470         {
01471             case 22:  // shot23_*
01472             case 158: // shot159_*
01473             case 187: // shot188_*
01474             case 198: // shot199_*
01475             case 407: // shot488_*
01476             case 514: // shot595_*
01477             case 543: // shot624_*
01478                 return true;
01479         default:
01480             return false;
01481         }
01482     }
01483 
01484     void BookmarkActiveCenter()
01485     {
01486         if (ShotHasBeenDumpedByTrecvidAtTheLastMinute(mActiveContext->GetCenter()))
01487         {
01488             ILOG_WARN("Shot " << mActiveContext->GetCenter() << " has been dumped by trecvid, not bookmarked.");
01489             return;
01490         }
01491         if (mDocument->AddCursorToBookmarked())
01492         {
01493             int shot = mActiveContext->GetCenter();
01494             if (mRotorBrowserListener)
01495                 mRotorBrowserListener->BookmarkEvent(this,shot,true);
01496             RemoveSpecificNegative(shot);
01497             ILOG_DEBUG( "Bookmarked active center " << shot << " POSITIVE." );
01498             RotorView* bookmarked =
01499                 mCache->GetViewFor(mActiveContext->GetName(),shot);
01500             bookmarked->Rename("bookmarked");
01501             bookmarked->MoveTo(1.0f, -1.0f, -2.0f, 1.0f, 1.0f);
01502             bookmarked->UpdateBookmarkState();
01503 
01504             if (mTrailBookmarks)
01505                 mTrailBookmarks->Push(shot);
01506         }
01507     }
01508 
01509     void BookmarkActiveCenterNegative()
01510     {
01511         BookmarkSpecificNegative(mActiveContext->GetCenter());
01512     }
01513 
01514     void BookmarkActiveCenterEx(bool positive)
01515     {
01516         if (positive)
01517             BookmarkActiveCenter();
01518         else
01519             BookmarkActiveCenterNegative();
01520     }
01521 
01522     void BookmarkSpecific(int shotID)
01523     {
01524         if (ShotHasBeenDumpedByTrecvidAtTheLastMinute(shotID))
01525         {
01526             ILOG_WARN("Shot " << shotID << " has been dumped by trecvid, not bookmarked.");
01527             return;
01528         }
01529 
01530         if (shotID < 0)
01531             return;
01532         int active = mDocument->CurKeyfr();
01533         mDocument->GotoKeyfr(mThreadSet->GetKeyframes()->GetShotRKF(shotID));
01534         if (mDocument->AddCursorToBookmarked())
01535         {
01536             if (mRotorBrowserListener)
01537                 mRotorBrowserListener->BookmarkEvent(this, shotID, true);
01538             RemoveSpecificNegative(shotID);
01539             ILOG_DEBUG("Bookmarked specific shot " << shotID << " POSITIVE.");
01540 
01541             if (mTrailBookmarks)
01542                 mTrailBookmarks->Push(shotID);
01543         }
01544         mDocument->GotoKeyfr(active);
01545     }
01546 
01547     void BookmarkSpecificNegative(int shotID)
01548     {
01549         if (shotID < 0)
01550             return;
01551         ThreadBookmarked *b;
01552         if (b = (ThreadBookmarked*)GetThreadByName("bookmarked_negative"))
01553         {
01554             int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shotID);
01555             b->AddShot(shotID, keyframe);
01556             ILOG_DEBUG( "Bookmarked specific shot " << shotID << " NEGATIVE." );
01557         }
01558         RemoveSpecific(shotID);
01559     }
01560 
01561     void BookmarkSpecificEx(int shotID, bool positive=true)
01562     {
01563         if (positive)
01564             BookmarkSpecific(shotID);
01565         else
01566             BookmarkSpecificNegative(shotID);
01567     }
01568 
01569     void RemoveSpecificNegative(int shotid)
01570     {
01571         ThreadBookmarked *b;
01572         if (b = (ThreadBookmarked*)GetThreadByName("bookmarked_negative"))
01573             b->RemoveShot(shotid);
01574     }
01575 
01576     void RemoveSpecific(int shotid)
01577     {
01578         ThreadBookmarked *b = (ThreadBookmarked*)GetThreadByName("bookmarked");
01579         if (b)
01580             b->RemoveShot(shotid);
01581         if (mRotorBrowserListener)
01582             mRotorBrowserListener->BookmarkEvent(this, shotid, false);
01583     }
01584 
01585     /* DoBookmarkCluster(as positive / as negative, force all shots)
01586         bookmarks a page in the cluster viewer
01587     */
01588     void DoBookmarkCluster(bool markPositive, bool force)
01589     {
01590         if (!mClusterSelector->IsActive()) return;
01591 
01592         ThreadBookmarked *positive =
01593             (ThreadBookmarked*)GetThreadByName("bookmarked");
01594         ThreadBookmarked *negative =
01595             (ThreadBookmarked*)GetThreadByName("bookmarked_negative");
01596 
01597         std::vector<int> shots = mClusterSelector->GetSelectedShots();
01598         ILOG_SYSTEM("cluster bookmarking " << shots.size() <<
01599                     " shots as " << (markPositive ? "POSITIVE" : "NEGATIVE"));
01600         for (int i=0; i<shots.size(); i++)
01601         {
01602             if (markPositive  && (force || !negative->Contains(shots[i])))
01603                     BookmarkSpecific(shots[i]);
01604             if (!markPositive && (force || !positive->Contains(shots[i])))
01605                     BookmarkSpecificNegative(shots[i]);
01606         }
01607         mClusterSelector->Show(mActiveContext);
01608     }
01609 
01610     void UpdateViewedShotBookmarks()
01611     {
01612         Impala::Core::Table::AnnotationTable *t = mCache->GetViewedShots();
01613         ThreadBookmarked *positive =
01614             (ThreadBookmarked*)GetThreadByName("bookmarked");
01615         ThreadBookmarked *negative =
01616             (ThreadBookmarked*)GetThreadByName("bookmarked_negative");
01617         if (!positive || !negative) return;
01618 
01619         int ctr = 0, booked = 0;
01620         for (int i=0; i < t->Size(); i++)
01621         {
01622             if (!t->IsPositive(i))
01623                 continue;
01624             ctr++;
01625             int shot = mThreadSet->GetSegmentation()->GetShotId(t->Get1(i));
01626 
01627             if (!positive->Contains(shot) && !negative->Contains(shot))
01628             {
01629                 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shot);
01630                 negative->AddShot(shot, keyframe);
01631                 booked ++;
01632             }
01633         }
01634         if (booked)
01635             ILOG_DEBUG("GetViewedShots(): " << ctr << " shots viewed, " <<
01636                        booked << " new bookmarks.");
01637     }
01638 
01639     void ShowHideStill(RotorView* v, bool show)
01640     {
01641         if (show)
01642             v->SetShowStills(mStills,mDocument->GetImSetStills());
01643         else
01644             v->SetHideStills();
01645     }
01646 
01647     void StartStopStills(bool start)
01648     {
01649         if (mAutoStills == STILLS_NONE)
01650             return;
01651 
01652         RotorView*  v;
01653         String      cName = mActiveContext->GetName();
01654         if (mClusterSelector->IsActive())
01655         {
01656             std::vector<int> shots = mClusterSelector->GetVisibleShots();
01657             for (int i=0; i<shots.size(); i++)
01658                 if (v = mCache->FindViewFor(cName,shots[i]))
01659                     ShowHideStill(v,start);
01660             return;
01661         }
01662 
01663         if (mAutoStills == STILLS_CENTER)
01664         {
01665             if (v = mCache->FindViewFor(cName,mActiveContext->GetCenter()))
01666                 ShowHideStill(v,start);
01667         }
01668         if (mAutoStills == STILLS_NEARCENTER)
01669         {
01670             for (int i=-2; i<=+2; i++)
01671                 if(v=mCache->FindViewFor(cName,mActiveContext->GetRelative(i)))
01672                     ShowHideStill(v,start);
01673         }
01674         if (mAutoStills == STILLS_ACTIVE)
01675         {
01676             int depth = mActiveContext->GetDepth();
01677             for (int i = -depth; i<= depth; i++)
01678                 if(v=mCache->FindViewFor(cName,mActiveContext->GetRelative(i)))
01679                     ShowHideStill(v,start);
01680         }
01681         if (mAutoStills == STILLS_ALL)
01682         {
01683             RotorViewList views = mCache->GetViews();
01684             RotorViewList::const_iterator i;
01685             for (i=views.begin(); i != views.end(); i++)
01686                 if ((*i)->IsCurrentlyShown())
01687                     ShowHideStill(*i,start);
01688         }
01689     }
01690 
01691     void StartStills()
01692     {
01693         StartStopStills(true);
01694     }
01695     void StopStills()
01696     {
01697         StartStopStills(false);
01698     }
01699 
01700     int AutoStills()
01701     {
01702         return mAutoStills;
01703     }
01704 
01705     void AutoStills(int mode)
01706     {
01707         StopStills();
01708         mAutoStills = mode;
01709         if (mAutoStills > STILLS_ALL)
01710             mAutoStills = STILLS_NONE;
01711         StartStills();
01712         String title = "Shot still player";
01713         switch (mAutoStills)
01714         {
01715             case STILLS_NONE:
01716                 ShowStatusStr(title,false); break;
01717             case STILLS_CENTER:
01718                 ShowStatusStr(title,"center shot only",oglDARKGREEN); break;
01719             case STILLS_NEARCENTER:
01720                 ShowStatusStr(title,"local area",oglDARKGREEN); break;
01721             case STILLS_ACTIVE:
01722                 ShowStatusStr(title,"active thread",oglDARKGREEN); break;
01723             case STILLS_ALL:
01724                 ShowStatusStr(title,"all shots",oglDARKGREEN); break;
01725         }
01726     }
01727 
01728 
01729     void ToggleAutoStills()
01730     {
01731         AutoStills(++mAutoStills);
01732     }
01733 
01734     void ToggleEnableVideoStream()
01735     {
01736         RotorView*  v;
01737         String      cName = mActiveContext->GetName();
01738         if (mClusterSelector->IsActive())
01739         {   // start playing all video's at once.
01740             std::vector<int> shots = mClusterSelector->GetVisibleShots();
01741             for (int i=0; i<shots.size(); i++)
01742             {
01743                 if (!(v = mCache->FindViewFor(cName,shots[i])))
01744                     continue;
01745                 if (v->GetVideoStillsEnabled())
01746                     v->DisableVideoStills();
01747                 else
01748                     v->EnableVideoStills(mDocument);
01749             }
01750             return;
01751         }
01752 
01753         if (v = mCache->FindViewFor(cName,mActiveContext->GetCenter()))
01754         {
01755             bool enabled = v->GetVideoStillsEnabled();
01756             if (enabled)
01757                 v->DisableVideoStills();
01758             else
01759                 v->EnableVideoStills(mDocument);
01760             ShowStatusStr("Center shot video player",!enabled);
01761         }
01762     }
01763 
01764     void TogglePlayUntilEnd()
01765     {
01766         if (mClusterSelector->IsActive())
01767             return;
01768 
01769         RotorView* center = mCache->FindViewFor(mActiveContext->GetName(), 
01770                                                 mActiveContext->GetCenter());
01771         if (center)
01772             center->SetPlayUntilEnd(!center->GetPlayUntilEnd());
01773         ShowStatusStr("Center shot plays until end of video",
01774                                    center->GetPlayUntilEnd());
01775     }
01776 
01777     void StopAutoStills()
01778     {
01779         StopStills();
01780         mAutoStills = STILLS_NONE;
01781         StartStills();
01782     }
01783 
01784     void TakeFocus()
01785     {
01786         oglFocusWnd = GetOGLWND();
01787         CheckFocus();
01788     }
01789 
01790     void ClusterSelect()
01791     {
01792         //StopStills();
01793         if (!mClusterSelector->IsActive())
01794         {
01795             ILOG_DEBUG("ClusterSelect(): showing...");
01796             mClusterSelector->Show(mActiveContext);
01797             if (mActiveContext->GetThread()->GetType() == Thread::VISUAL)
01798                 mClusterSelector->SetPagemode(false);
01799             else
01800                 mClusterSelector->SetPagemode(true);
01801         }
01802         else
01803         {
01804             ILOG_DEBUG("ClusterSelect(): hiding...");
01805             mClusterSelector->Hide();
01806         }
01807     }
01808 
01809     Thread* GetThreadByName(CString name)
01810     {
01811         return mThreadSet->GetThreadByName(name);
01812     }
01813 
01814     virtual void
01815     OnRectangleSelect(int shotID, float x, float y, float w, float h)
01816     {
01817         ILOG_DEBUG("OnRectangleSelect: shot ID="<<shotID<<" x=" << x <<
01818                    " y=" << y << " w=" << w << " h=" << h);
01819         int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shotID);
01820         DoQueryByRegion(keyframe, x, y, w, h);
01821     }
01822 
01823     virtual void OnRectangleSelectByKeyframe(int keyframeID, float x, float y,
01824                                              float w, float h)
01825     {
01826         ILOG_DEBUG("OnRectangleSelect: keyframe ID="<<keyframeID<<" x=" <<
01827                    x << " y=" << y << " w=" << w << " h=" << h);
01828         DoQueryByRegion(keyframeID, x, y, w, h);
01829     }
01830 
01831     bool ValidateContext(CString name)
01832     {
01833         RotorBrowserContext* ctx = GetContextByName(name);
01834         if (!ctx || !ctx->ThreadValid())
01835             return false;
01836         return true;
01837     }
01838 
01839 private:
01840     void InitHelp()
01841     {
01842         int w = WndWidth(), h = WndHeight();
01843         if (w < 600 || h < 200)
01844             mHelpViewer = new GUI::HelpViewer(this,0,0,w,h);
01845         else
01846             mHelpViewer = new GUI::HelpViewer(this,(w-600)/2,60,600,h-120);
01847         mHelpViewer->ConnectTo(this);
01848         mHelpViewer->SetVisible(false);
01849     }
01850 
01851     void ShowStatusStr(String s1, String s2, ULONG col=0)
01852     {
01853         if (!mStatusOverlay) return;
01854 
01855         mStatusOverlay->ShowStatus(s1,s2,col);
01856     }
01857 
01858     void ShowStatusStr(String s1, bool mode)
01859     {
01860         if (!mStatusOverlay) return;
01861 
01862         mStatusOverlay->ShowStatus(s1,mode);
01863     }
01864 
01865     void Printf3D(float x, float y, float z,
01866                   float scaleX, float scaleY, float scaleZ, String str)
01867     {
01868         glPushMatrix();
01869         int fBase = mFontHandler->GetFontBase(this);
01870         oglSys.Printf3D(fBase,x,y,z,scaleX,scaleY,scaleZ,str.c_str());
01871         glPopMatrix();
01872     }
01873 
01874     void DoReturnToFirstQuery()
01875     {
01876         if (!mHasReturnQuery) return;
01877 
01878         mThreadSet->RemoveThread("shots_initialquery");
01879         Thread* t = GetThreadByName("shots_returnquery");
01880         mThreadSet->CopyToShotsThread(t,"initialquery");
01881         ILOG_DEBUG("Returning to previous query, position = "<<mReturnPosition);
01882         mHasReturnQuery = false;
01883         UpdateViewsToContext();
01884         ReloadCrossBrowser(mReturnPosition);
01885     }
01886 
01887     void DoShowBookmarksThread()
01888     {
01889         // this toggles between showing bookmarks and showing the active query
01890         if (mHasReturnQuery)
01891         {
01892             DoReturnToFirstQuery();
01893             return;
01894         }
01895         // RvB: Added to handle nothing bookmarked
01896         Thread* t = GetThreadByName("bookmarked");
01897         if (t->GetLength()<1) return;
01898 
01899         ClearReturnQuery();
01900         if (!mHasReturnQuery)
01901         {
01902             t = GetThreadByName("shots_initialquery");
01903             mThreadSet->CopyToShotsThread(t,"returnquery");
01904             mHasReturnQuery = true;
01905             mReturnPosition = GetContext("shots_initialquery")->GetCenter();
01906             ILOG_DEBUG("Stored return query with position " << mReturnPosition);
01907         }
01908         mThreadSet->RemoveThread("shots_initialquery");
01909         mThreadSet->CopyToShotsThread(GetThreadByName("bookmarked"), 
01910                                       "initialquery");
01911         ILOG_DEBUG("Showing bookmark thread");
01912         UpdateViewsToContext();
01913         mActiveContext->GoFirst();
01914         UpdateViewsToContext();
01915     }
01916 
01917     void ClearReturnQuery()
01918     {
01919         mThreadSet->RemoveThread("shots_returnquery");
01920         mHasReturnQuery = false;
01921         mReturnPosition = 0;
01922     }
01923 
01924     void DoVisualQuery(String type)
01925     {
01926         if (mBrowseMode == MODE_FORKBROWSER)
01927         {
01928             ILOG_WARN("DoVisualQuery redundant in ForkBrowser, not executing.");
01929             return;
01930         }
01931 
01932         int active = mActiveContext->GetCenter();
01933 
01934         String tname = "vis_" + type + "_" + MakeString(active);
01935         if (mBrowseMode==MODE_ROTORBROWSER && GetThreadByName("shots_"+tname))
01936         {
01937             ILOG_WARN("DoVisualQuery: thread " << tname << " already exists." );
01938             return;
01939         }
01940 
01941         active = mThreadSet->GetKeyframes()->GetShotRKF(active);
01942         std::list<KeyframeResult> visual =
01943             mVisualQueryEngine->QueryVisual(type, active);
01944         if (visual.empty())
01945         {
01946             ILOG_WARN("DoVisualQuery: " << type << " no results");
01947             return;
01948         }
01949 
01950         if (mBrowseMode == MODE_CROSSBROWSER)
01951         {
01952             ClearReturnQuery();
01953             if (!mHasReturnQuery)
01954             {
01955                 Thread* t = GetThreadByName("shots_initialquery");
01956                 mThreadSet->CopyToShotsThread(t,"returnquery");
01957                 mHasReturnQuery = true;
01958                 mReturnPosition = GetContext("shots_initialquery")->GetCenter();
01959                 ILOG_DEBUG("Stored return query with position " <<
01960                            mReturnPosition);
01961             }
01962             mThreadSet->RemoveThread("shots_initialquery");
01963             mThreadSet->AddThreadShots("initialquery", visual);
01964             ReloadCrossBrowser();
01965             UpdateViewsToContext();
01966             return;
01967         }
01968 
01969         // mode == ROTORBROWSER
01970         mThreadSet->AddThreadShots(tname, visual);
01971         UpdateViewsToContext();
01972         SwitchToContext("shots_" + tname);
01973         UpdateViewsToContext();
01974     }
01975 
01976 /*
01977     void DoVisualQuery(String type)
01978     {
01979         if (mBrowseMode == MODE_FORKBROWSER) {
01980             ILOG_WARN("DoVisualQuery redundant in ForkBrowser, not executing.");
01981             return;
01982         }
01983 
01984         int active = mActiveContext->GetCenter();
01985 
01986         if (mBrowseMode == MODE_CROSSBROWSER)
01987         {
01988             active = mThreadSet->GetKeyframes()->GetShotRKF(active);
01989             std::list<KeyframeResult> visual =
01990                 mVisualQueryEngine->QueryVisual(type, active);
01991 if (visual.empty())
01992     return;
01993             ClearReturnQuery();
01994             if (!mHasReturnQuery)
01995             {
01996                 Thread* t = GetThreadByName("shots_initialquery");
01997                 mThreadSet->CopyToShotsThread(t,"returnquery");
01998                 mHasReturnQuery = true;
01999                 mReturnPosition = GetContext("shots_initialquery")->GetCenter();
02000                 ILOG_DEBUG("Stored return query with position " <<
02001                            mReturnPosition);
02002             }
02003             mThreadSet->RemoveThread("shots_initialquery");
02004             mThreadSet->AddThreadShots("initialquery", visual);
02005             ReloadCrossBrowser();
02006             UpdateViewsToContext();
02007             return;
02008         }
02009 
02010         String tname = "vis_" + type + "_" + MakeString(active);
02011         if (GetThreadByName("shots_" + tname) != NULL)
02012         {
02013             ILOG_WARN("DoVisualQuery: thread " << tname << " already exists." );
02014             return;
02015         }
02016         active = mThreadSet->GetKeyframes()->GetShotRKF(active);
02017         std::list<KeyframeResult> visual =
02018             mVisualQueryEngine->QueryVisual(type, active);
02019 if (visual.empty())
02020     return;
02021         mThreadSet->AddThreadShots(tname, visual);
02022         UpdateViewsToContext();
02023         SwitchToContext("shots_" + tname);
02024         UpdateViewsToContext();
02025     }
02026 */
02027     void
02028     DoQueryByRegion(int keyframeID, float x, float y, float w, float h)
02029     {
02030         ILOG_DEBUG("DoQueryByRegion: keyframe ID="<<keyframeID<<" x=" << x
02031                    << " y=" << y << " w=" << w << " h=" << h);
02032 
02033         if (mBrowseMode == MODE_FORKBROWSER) {
02034             ILOG_ERROR("Handling of Query By Region queries in ForkBrowser " <<
02035                        "not yet implemented.");
02036             return;
02037         }
02038 
02039         if (mBrowseMode == MODE_CROSSBROWSER)
02040         {
02041             std::list<KeyframeResult> qbyr =
02042                 mVisualQueryEngine->QueryByRegion(keyframeID,x,y,x+w,y+h);
02043             if (qbyr.size() > 1)
02044             {
02045                 ILOG_DEBUG("Got "<<qbyr.size()<<" results from webservice.");
02046                 std::ostringstream bla;
02047                 bla << "Found " << qbyr.size() << " query by region results.";
02048                 ShowStatusStr("Query by Region",bla.str(),oglGREEN);
02049                 mThreadSet->RemoveThread("shots_initialquery");
02050                 mThreadSet->AddThreadShots("initialquery", qbyr);
02051                 UpdateViewsToContext();
02052                 ReloadCrossBrowser();
02053             }
02054             else
02055             {
02056                 ILOG_DEBUG("Got no results from webservice.");
02057                 char *t = "No query by region result found for this selection.";
02058                 ShowStatusStr("Error",t,oglRED);
02059             }
02060             return;
02061         }
02062         String tname = "qbyr_" + MakeString(keyframeID);
02063         if (GetThreadByName("shots_" + tname) != NULL)
02064             ILOG_WARN( "thread " << tname << " already exists." );
02065 
02066         std::list<KeyframeResult> qbyr =
02067             mVisualQueryEngine->QueryByRegion(keyframeID,x,y,x+w,y+h);
02068 
02069         mThreadSet->AddThreadShots(tname, qbyr);
02070         UpdateViewsToContext();
02071         SwitchToContext("shots_" + tname);
02072         UpdateViewsToContext();
02073     }
02074 
02075     void AddRelevantContexts()
02076     {
02077         int active = mActiveContext->GetCenter();
02078         ILOG_DEBUG("Searching for relevant contexts for " <<
02079                     mActiveContext->GetName());
02080         TableThreadWidthId *queue =
02081             new TableThreadWidthId(mThreadSet->GetNrThreads());
02082         for (int i=0; i < mThreadSet->GetNrThreads(); i++)
02083         {
02084             Thread *t = mThreadSet->GetThread(i);
02085             if (t->GetName() == "shots_videos")
02086                 continue;
02087             if (t->GetType() == Thread::RANK && !mShowRankThreads)
02088                 continue;
02089             int relevancy = IsRelevant(t, active);
02090             if (relevancy > 0)
02091                 queue->Add(relevancy, t);
02092         }
02093         //Table::Sort(queue, 1);
02094         Impala::Core::Table::Sort(queue, 1, true); // ascending
02095 
02096         for (int i=0; i < queue->Size(); i++)
02097         {
02098             if (i > 4 && queue->Get1(i) > 3)
02099                 break;
02100             if (i > 6)
02101                 break;
02102             AddContext(queue->Get2(i), active);
02103         }
02104         // RvB: Added to prevent memory-leak
02105         delete queue;
02106         ILOG_DEBUG( " end of relevant context search." );
02107     }
02108 
02109     /*
02110         relevancy is determined as follows:
02111             0: not relevant
02112             1: relevant: time and initialquery
02113             2: relevant: visually similar
02114             3: relevant: generated shots threads / 2k5 threads
02115             4+ relevant: rank thread, relevancy indicates rank - 4
02116     */
02117     int IsRelevant(Thread *t, int position)
02118     {
02119         switch (t->GetType())
02120         {
02121             case Thread::VISUAL:
02122             case Thread::BOOKMARK:
02123             case Thread::HISTORY:
02124                 return 0;
02125             case Thread::TIME:
02126                 return 1;
02127             case Thread::SHOTS:
02128                 if (t->GetName() == "shots_initialquery") return 1;
02129                 if (t->GetName() == "shots_supplement")   return 0;
02130                 if (t->GetName().find("vis_") != String::npos)
02131                 {
02132                     if (t->GetShotPosition(position) < mTopN &&
02133                         t->GetShotPosition(position) >= 0)
02134                         return 2;
02135                     return 0;
02136                 }
02137                 return 3;
02138             default:
02139                 int pos = t->GetShotPosition(position);
02140                 if (pos >=0 && pos < mTopN)
02141                     return pos+4;
02142                 // HARD CODED ERROR !!! WARNING!!
02143                 if (pos > 0 && pos < 79484 &&
02144                     t->GetName().find("rank_thread_all") != String::npos)
02145                     return 3;
02146         }
02147         return 0;
02148     }
02149 
02150     void ManageContexts()
02151     {
02152         if (mBrowseMode == MODE_ROTORBROWSER)
02153             return ManageRotorContexts();
02154     }
02155 
02156     void ManageRotorContexts()
02157     {
02158         mBusyManaging = true;
02159 
02160         // create lists of active contexts for the new position:
02161         RotorBrowserContextList newposition;
02162 
02163         // erase current contexts but not active one, and not context "time":
02164         RotorBrowserContextList::iterator context;
02165         for (context=mContexts.begin(); context!=mContexts.end(); context++)
02166         {
02167             if ((*context)->GetName() == "time" ||
02168                 IsRelevant((*context)->GetThread(),mActiveContext->GetCenter()))
02169             {
02170                 // context still relevant: keep
02171                 newposition.push_back(*context);
02172                 if (mManageDepth)
02173                     (*context)->SetDepth(4);
02174                 continue;
02175             }
02176             delete (*context);
02177         }
02178         mContexts.clear();
02179         mContexts = newposition; // is this legal memory-wise?
02180         AddRelevantContexts();
02181 
02182         if (mManageDepth)
02183             mActiveContext->SetDepth(6);
02184         mBusyManaging = false;
02185         RepositionContexts();
02186     }
02187 
02188     Thread* GetInitBrowserThread(char* str)
02189     {
02190         ILOG_SYSTEM("Init " << str);
02191         Thread *query = GetThreadByName("shots_initialquery");
02192         if (query == NULL || query->GetLength() == 0)
02193         {
02194             ILOG_WARN("tried to inialize " << str << " but no initial " <<
02195                       "query present. Aborting." );
02196             SetBrowseMode(MODE_ROTORBROWSER);
02197         }
02198         return query;
02199     }
02200 
02201     int CheckInitBrowserFirstShot(Thread* query, char* str)
02202     {
02203         int pos;
02204         if ((pos = query->GetFirstShot()) < 0)
02205         {
02206             ILOG_WARN("tried to inialize " << str << " but initial " <<
02207                       "query has no first shot. Switching to RotorBrowser." );
02208             SetBrowseMode(MODE_ROTORBROWSER);
02209         }
02210         return pos;
02211     }
02212 
02213     void InitCrossBrowser(int startposition = -1)
02214     {
02215         Thread* query = GetInitBrowserThread("CrossBrowser");
02216         if (!query) return;
02217 
02218         int pos = mActiveContext ? mActiveContext->GetCenter() : 0;
02219         if (pos == 0)
02220         {
02221             if ((pos = CheckInitBrowserFirstShot(query,"CrossBrowser")) < 0)
02222                 return;
02223             if (startposition >= 0)
02224                 pos = startposition;
02225             ILOG_DEBUG("setting up CrossBrowser start position at " << pos);
02226         }
02227 
02228         if (mActiveContext != NULL)
02229             delete mActiveContext;
02230 
02231         RotorBrowserContextList::iterator context;
02232         for (context=mContexts.begin(); context!=mContexts.end(); context++)
02233             delete (*context);
02234         mContexts.clear();
02235 
02236         mActiveContext = new RotorBrowserContext(mCache,query,pos,M_PI/2,6);
02237         mActiveContext->SetSwallowThread(GetThreadByName("virtual_hidden"));
02238         mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02239 
02240         RotorBrowserContext *time =
02241             new RotorBrowserContext(mCache,GetThreadByName("time"),pos,0.0,6);
02242         time->SetSwallowThread(GetThreadByName("virtual_hidden"));
02243         time->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02244         mContexts.push_back(time);
02245     }
02246 
02247     void InitForkBrowser()
02248     {
02249         Thread* query = GetInitBrowserThread("ForkBrowser");
02250         if (!query) return;
02251 
02252         RotorBrowserContext::SetGlobalShotSwallow(true);
02253         // FORK_TODO
02254         mForkLastQueryShot = -1;
02255 
02256         int position = mActiveContext ? mActiveContext->GetCenter() : 0;        
02257         if (position == 0)
02258         {
02259             if ((position = CheckInitBrowserFirstShot(query,"ForkBrowser")) < 0)
02260                 return;
02261             ILOG_DEBUG("setting up ForkBrowser start position at " << position);
02262         }
02263 
02264         // remove all other contexts:
02265         if (mActiveContext != NULL)
02266             delete mActiveContext;
02267 
02268         RotorBrowserContextList::iterator context;
02269         for (context = mContexts.begin(); context != mContexts.end(); context++)
02270             delete (*context);
02271         mContexts.clear();
02272 
02273         Thread* threadHidden = GetThreadByName("virtual_hidden");
02274 
02275         // set vertical context (direction UP) to QUERY RESULTS:
02276         mActiveContext =
02277             new RotorBrowserContext(mCache, query, position, M_PI/2, 6);
02278         mActiveContext->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02279         mActiveContext->SetSwallowThread(threadHidden);
02280         mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02281 
02282         // set vertical context (direction DOWN) to HISTORY:
02283         Thread* threadHistory = GetThreadByName("history");
02284         RotorBrowserContext *history =
02285             new RotorBrowserContext(mCache,threadHistory,position,M_PI/2,6);
02286         history->SetDrawDirection(RotorBrowserContext::DIRECTION_DOWN);
02287         history->SetSwallowThread(threadHidden);
02288         history->SetSwallowMode(RotorBrowserContext::SWALLOW_NONE);
02289         mContexts.push_back(history);
02290 
02291         // set horizontal context to TIME RESULTS:
02292         RotorBrowserContext *time =
02293            new RotorBrowserContext(mCache,GetThreadByName("time"),position,0,6);
02294         time->SetSwallowThread(threadHidden);
02295         time->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02296         mContexts.push_back(time);
02297 
02298         Thread* visSemGabor = GetThreadByName("visual_vissemgabor");
02299         RotorBrowserContext *visual =
02300             new RotorBrowserContext(mCache,visSemGabor,position,M_PI/4,6);
02301         visual->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02302         visual->SetSwallowThread(threadHidden);
02303         visual->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02304         mContexts.push_back(visual);
02305 
02306         Thread* visSem = GetThreadByName("visual_vissem");
02307         RotorBrowserContext *contextual =
02308             new RotorBrowserContext(mCache,visSem,position,M_PI/4+M_PI/2,6);
02309         contextual->SetDrawDirection(RotorBrowserContext::DIRECTION_UP);
02310         contextual->SetSwallowThread(threadHidden);
02311         contextual->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02312         mContexts.push_back(contextual);
02313     }
02314 
02315     void InitRotorBrowser()
02316     {
02317         RotorBrowserContext *query = GetContext("shots_initialquery");
02318         ILOG_SYSTEM( "Init RotorBrowser" );
02319         mInitialQueryPosition = -1;
02320         if (query)
02321             query->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02322         if (mActiveContext)
02323             mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02324     }
02325 
02326     RotorBrowserContext* GetContextByName(String name) 
02327     {
02328         if (mActiveContext->GetName() == name)
02329             return mActiveContext;
02330 
02331         RotorBrowserContextList::iterator context;
02332         for (context=mContexts.begin(); context!=mContexts.end(); context++)
02333         {
02334             if ((*context)->GetName() == name)
02335                 return *context;
02336         }
02337         return NULL;
02338     }
02339 
02340     RotorBrowserContext* FindContextForPosition(int ID)
02341     {
02342         if (mActiveContext->ShowsPosition(ID))
02343             return mActiveContext;
02344 
02345         RotorBrowserContextList::iterator context;
02346         for (context=mContexts.begin(); context!=mContexts.end(); context++)
02347         {
02348             if ((*context)->ShowsPosition(ID))
02349                 return *context;
02350         }
02351         return NULL;
02352     }
02353 
02354     bool HasContext(String name)
02355     {
02356         return GetContextByName(name) != NULL;
02357     }
02358 
02359     bool SwitchToPreviousContext()
02360     {
02361         return SwitchToNextContext(-1);
02362     }
02363 
02364     bool SwitchToNextContext(int direction = +1) 
02365     {
02366         if (mBrowseMode != MODE_ROTORBROWSER)
02367             return false;
02368         if (mContexts.size() == 0)
02369         {
02370             ILOG_DEBUG( "RotorBrowser::SwitchToNextContext: no other contexts");
02371             return false;
02372         }
02373         RotorBrowserContext *next;
02374         if (direction < 0)
02375         {
02376             next = mContexts.back();
02377             mContexts.pop_back();
02378             mContexts.push_front(mActiveContext);
02379         }
02380         else
02381         {
02382             next = mContexts.front();
02383             mContexts.pop_front();
02384             mContexts.push_back(mActiveContext);
02385         }
02386         if (mManageDepth)
02387         {
02388             next->SetDepth(5);
02389             mActiveContext->SetDepth(3);
02390         }
02391         mActiveContext = next;
02392         ILOG_DEBUG("RotorBrowser::SwitchToNextContext: active context now: " <<
02393                    mActiveContext->GetName() );
02394         if (mRotorBrowserListener)
02395             mRotorBrowserListener->ContextChangeEvent(this, mActiveContext);
02396         RepositionContexts();
02397         return true;
02398     }
02399 
02400     bool SwitchToContext(String name)
02401     {
02402         if (mActiveContext && mActiveContext->GetName() == name)
02403             return true;
02404         if (mContexts.size() == 0) {
02405             ILOG_DEBUG( "SwitchToContext: no other contexts found." );
02406             return false;
02407         }
02408         if (mActiveContext == NULL)
02409         {
02410             mActiveContext = mContexts.front();
02411             mContexts.pop_front();
02412             ILOG_WARN("no active context found. Active context set to "
02413                       << mActiveContext->GetName() );
02414         }
02415 
02416         String scontext = mActiveContext->GetName();
02417         int maxr = 0;
02418         while (mActiveContext->GetName() != name)
02419         {
02420             RotorBrowserContext *next = mContexts.front();
02421             mContexts.pop_front();
02422             if (mBrowseMode == MODE_ROTORBROWSER && mManageDepth)
02423             {
02424                 next->SetDepth(5);
02425                 mActiveContext->SetDepth(3);
02426             }
02427             mContexts.push_back(mActiveContext);
02428             mActiveContext = next;
02429             if (mActiveContext->GetName() == scontext && ++maxr==2)
02430                 return false; // not found after making full circle
02431         }
02432         ILOG_DEBUG("RotorBrowser::SwitchToContext: active context now: "
02433                    << mActiveContext->GetName() );
02434         if (mRotorBrowserListener)
02435             mRotorBrowserListener->ContextChangeEvent(this, mActiveContext);
02436         RepositionContexts();
02437         return true;
02438     }
02439 
02440     RotorBrowserContext* GetContext(String name)
02441     {
02442         if (mActiveContext->GetName() == name)
02443             return mActiveContext;
02444 
02445         RotorBrowserContextList::iterator context;
02446         for (context=mContexts.begin(); context != mContexts.end(); context++)
02447         {
02448             if ((*context)->GetName() == name)
02449                 return *context;
02450         }
02451         return NULL;
02452     }
02453 
02454     void RepositionContexts()
02455     {
02456         if (mBusyManaging || mBrowseMode != MODE_ROTORBROWSER)
02457             return;
02458 
02459                 if (mActiveHorizontal)
02460                         mActiveContext->SetDirection(0.0);
02461 
02462         double cDi = M_PI / ((double)mContexts.size()+1);
02463                 double cD  = mActiveContext->GetDirection() + cDi;
02464         RotorBrowserContextList::const_iterator context;
02465         for (context=mContexts.begin(); context!=mContexts.end(); context++)
02466         {
02467             (*context)->SetDirection(cD);
02468             cD += cDi;
02469         }
02470     }
02471 
02472     void CheckFocus(bool force=false)
02473     {
02474         bool hasFocus = (GetOGLWND() == oglFocusWnd);
02475         if ((hasFocus && !mHadFocus) || (force && mHadFocus))
02476         {
02477             mHadFocus = true;
02478             if (!force)
02479                 mBackNormal = GetBorderBackground();
02480             if (mBrowseMode == MODE_ROTORBROWSER)
02481                 SetBorderBackground(0x80802020);
02482             else if (mBrowseMode == MODE_FORKBROWSER)
02483                 SetBorderBackground(0x802020A0);
02484             else
02485                 SetBorderBackground(0x80206020);
02486         }
02487         if (!hasFocus && mHadFocus)
02488         {
02489             mHadFocus = false;
02490             SetBorderBackground(mBackNormal);
02491         }
02492     }
02493 
02494     void InitKB(String keyStr, String dfltStr0,
02495                 String dfltStr1="", String dfltStr2="",
02496                 String dfltStr3="", String dfltStr4="",
02497                 String dfltStr5="", String dfltStr6="")
02498     {
02499         KeyBindingsMap& kb = mKeyBindings;
02500         keyStr = mPreFix + keyStr;
02501         InitKeyBinding(kb, keyStr, dfltStr0, dfltStr1, dfltStr2, dfltStr3,
02502                        dfltStr4, dfltStr5, dfltStr6);
02503     }
02504 
02505     void InitKeyBindings()
02506     {
02507         KeyBindingsMap& kb = mKeyBindings;
02508 
02509         InitKB("CsBookPositive",                  "space");
02510         InitKB("CsBookPositiveForce",             "shift#space");
02511         InitKB("CsBookNegative",                  "x");
02512         InitKB("CsBookNegativeForce",             "X");
02513 
02514         InitKB("StdToggleShowBookmarks",          "b");
02515         InitKB("StdStopAutoStills",               "esc");
02516         InitKB("StdToggleAutoStills",             "\t");
02517         InitKB("StdToggleVideoStream",            "1");
02518         InitKB("StdTogglePlayUntilEnd",           "2");
02519         InitKB("StdIncrAutoStillSpeed",           "=");
02520         InitKB("StdDecrAutoStillSpeed",           "-");
02521         InitKB("StdIncrAnimationSpeed",           "]");
02522         InitKB("StdDecrAnimationSpeed",           "[");
02523         InitKB("StdToggleShowHelp",               "h", "H");
02524         InitKB("StdCrossBrowserMode",             "fn5");
02525         InitKB("StdRotorBrowserMode",             "fn6");
02526         InitKB("StdForkBrowserMode",              "fn7");
02527         InitKB("StdToggleShotSwallow",            "`");
02528         InitKB("StdToggleShotSwallowThread",      "~");
02529         InitKB("StdToggleKeepCenterCentered",     ".", "l");
02530         InitKB("StdBookmarkCenterPositive",       "space");
02531         InitKB("StdBookmarkCenterNegative",       "x", "X");
02532         InitKB("StdClusterSelect",                "f", "F");
02533         InitKB("StdClearViewedCache",             "O");
02534         InitKB("StdJudgeBrowseMode",              "ctrl-shift#l");
02535         InitKB("StdToggleAutoSelectNegatives",    "L");
02536 
02537         InitKB("VisualQuery_vissemgabor",         "V");
02538         InitKB("VisualQuery_vissem",              "B");
02539         InitKB("VisualQuery_fusionvissemgabor",   "N");
02540         InitKB("VisualQuery_labhistogram",        "M");
02541 
02542         InitKB("RbGoForward",                     "d");
02543         InitKB("RbGoBackward",                    "a");
02544         InitKB("RbGoFirst",                       "q");
02545         InitKB("RbGoLast",                        "e");
02546         InitKB("RbBookmarkNext",                  "D");
02547         InitKB("RbBookmarkPrev",                  "A");
02548         InitKB("RbSwitchToContextNext",           "w");
02549         InitKB("RbSwitchToContextPrev",           "W");
02550         InitKB("RbSwitchToContextTime",           "t");
02551         InitKB("RbSwitchToContextBookmark",       "T");
02552         InitKB("RbReturnLastInitialQuery",        "r", "R");
02553         InitKB("RbToggleShowRankThreads",         "o");
02554 
02555         InitKB("CbGoFirst",                       "q");
02556         InitKB("CbGoLast",                        "e");
02557         InitKB("CbGoInitialQuery",                "r", "R");
02558         InitKB("CbGoUp",                          "w", "up");
02559         InitKB("CbGoDown",                        "s", "down");
02560         InitKB("CbGoLeft",                        "a", "left");
02561         InitKB("CbGoRight",                       "d", "right");
02562         InitKB("CbBookmarkPrevNegative",          "ctrl#a", "ctrl#left");
02563         InitKB("CbBookmarkNextNegative",          "ctrl#d", "ctrl#right");
02564         InitKB("CbBookmarkPrevPositive",          "A","shift#left");
02565         InitKB("CbBookmarkNextPositive",          "D", "shift#right");
02566         InitKB("CbBookmarkUpNegative",            "ctrl#w", "ctrl#up");
02567         InitKB("CbBookmarkDownNegative",          "ctrl#s", "ctrl#down");
02568         InitKB("CbBookmarkUpPositive",            "W", "shift#up");
02569         InitKB("CbBookmarkDownPositive",          "s", "shift#down");
02570 
02571         InitKB("FbTimeBackward",                  "a", "left");
02572         InitKB("FbTimeForward",                   "d", "right");
02573         InitKB("FbBookmarkPositiveTimeBackward",  "A", "shift#left");
02574         InitKB("FbBookmarkPositiveTimeForward",   "D", "shift#right");
02575         InitKB("FbBookmarkNegativeTimeBackward",  "ctrl#a", "ctrl#left");
02576         InitKB("FbBookmarkNegativeTimeForward",   "ctrl#d", "ctrl#right");
02577         InitKB("FbLastHistory",                   "s", "down");
02578         InitKB("FbBookmarkPositiveHistoryGoLast", "S", "shift#down");
02579         InitKB("FbBookmarkNegativeHistoryGoLast", "ctrl#s","ctrl#down");
02580         InitKB("FbLastQueryShot",                 "r");
02581         InitKB("FbQueryForward",                  "w", "up");
02582         InitKB("FbBookmarkPositiveQueryForward",  "W", "shift#up");
02583         InitKB("FbBookmarkNegativeQueryForward",  "ctrl#w","ctrl#up");
02584         InitKB("FbGaborForward",                  "e");
02585         InitKB("FbBookmarkPositiveGaborForward",  "E");
02586         InitKB("FbBookmarkNegativeGaborForward",  "ctrl#e");
02587         InitKB("FbVissemForward",                 "q");
02588         InitKB("FbBookmarkPositiveVissemForward", "Q");
02589         InitKB("FbBookmarkNegativeVissemForward", "ctrl#q");
02590     }
02591 
02592     void
02593     Init(ThreadSet *threadset, SegmentationDocument *document, String preFix)
02594     {
02595         ILOG_DEBUG("RotorBrowser::init()");
02596         oglSys.SetAllowCameraMove(GetOGLWND(), CamMove_Keys | CamMove_Mouse);
02597 
02598         CmdOptions &options   = CmdOptions::GetInstance();
02599 
02600         mRotorBrowserListener = NULL;
02601         mThreadSet            = threadset;
02602         mDocument             = document;
02603         mPreFix               = options.GetString("RbKeybindingPrefix", preFix);
02604         mPrograms             = 0;
02605 
02606         mBrowseMode           = MODE_ROTORBROWSER;
02607         mAutoStills           = STILLS_NONE;
02608         mBackNormal           = GetBackground();
02609         mTopN                 = 30;
02610         mInitialQueryPosition = -1;
02611         mReturnPosition       = 0;
02612         mDisabledCenterVideo  = -1;
02613 
02614         // only allocate trails when they're actually used:
02615         mTrailBookmarks       = 0;
02616         mTrailVisited         = 0;
02617         mTrailHistory         = 0;
02618         mTrailVisibleTime     = 0;
02619         mTrailVisibleQuery    = 0;
02620         mTrailVisibleVisualA  = 0;
02621         mTrailVisibleVisualB  = 0;
02622 
02623         mHadFocus             = false;
02624         mShowRankThreads      = false;
02625         mEnableShotSwallow    = false;
02626         mKeepCenterCentered   = false;
02627         mBusyManaging         = false;
02628         mHasReturnQuery       = false;
02629         mActiveHorizontal     = true;
02630         mShowDirection        = true;
02631         mManageContexts       = true;
02632         mManageDepth          = true;
02633 
02634         Thread* timeThr       = GetThreadByName("time");
02635         Thread* hiddenThr     = GetThreadByName("virtual_hidden");
02636 
02637         mFontHandler          = new FontHandler();
02638         mStatusOverlay        = new StatusOverlayWindow(this);
02639         mCache                = new RotorViewCache(this, threadset, this);
02640         mClusterSelector      = new ThreadClusterSelector(mCache);
02641         mVisualQueryEngine    = new VisualQueryEngine(mThreadSet,mTopN*2);
02642         mStills               = new Stills(mDocument->GetVideoSet(),"stills");
02643         mActiveContext        = new RotorBrowserContext(mCache,timeThr,0,0.0,5);
02644 
02645         mActiveContext->SetSwallowThread(hiddenThr);
02646         mActiveContext->SetSwallowMode(RotorBrowserContext::SWALLOW_ALL);
02647 
02648         SetEnableShotSwallow(false);
02649         RotorView::SetStillFrameWait(15);
02650 
02651         InitHelp();
02652         InitKeyBindings();
02653 
02654         // RvB: Added next 2 lines
02655         // Ork: disabled next line, in linux you cannot use alt+rmouse combinations,
02656         //      and keyboard zooming wasn't working.
02657         SetDisableOGLViewKeys(false);
02658         SetBorderBackground(0x80202020);
02659         // TODO: set active position based on mDocument
02660     }
02661 
02662     KeyBindingsMap                  mKeyBindings;
02663     String                          mPreFix;
02664 
02665     ThreadSet*                      mThreadSet;
02666     SegmentationDocument*           mDocument;
02667     VisualQueryEngine*              mVisualQueryEngine;
02668     ThreadClusterSelector*          mClusterSelector;
02669     Samples::ProgramNameReader*     mPrograms;
02670     Stills*                         mStills;
02671 
02672     RotorBrowserContextList         mContexts;
02673     RotorBrowserContext*            mActiveContext;
02674     RotorBrowserListener*           mRotorBrowserListener;
02675     RotorViewCache*                 mCache;
02676 
02677     // minimap shot trail support:
02678     ShotTrail*                      mTrailVisited;
02679     ShotTrail*                      mTrailBookmarks;
02680     ShotTrail*                      mTrailHistory;
02681     ShotTrail*                      mTrailVisibleTime;
02682     ShotTrail*                      mTrailVisibleQuery;
02683     ShotTrail*                      mTrailVisibleVisualA;
02684     ShotTrail*                      mTrailVisibleVisualB;
02685 
02686     Visualization::GUI::HelpViewer* mHelpViewer;
02687     FontHandler*                    mFontHandler;
02688     StatusOverlayWindow*            mStatusOverlay;
02689 
02690     int                             mTopN;
02691     int                             mBrowseMode;
02692     int                             mForkLastQueryShot;
02693     int                             mInitialQueryPosition;
02694     int                             mReturnPosition;
02695     int                             mAutoStills;
02696 
02697     // SK: used to prevent center video playback over and over for
02698     // erroneous video's
02699     int                             mDisabledCenterVideo;
02700 
02701     bool                            mHadFocus;
02702     bool                            mShowDirection;
02703     bool                            mActiveHorizontal;
02704     bool                            mManageContexts;
02705     bool                            mBusyManaging;
02706     bool                            mManageDepth;
02707     bool                            mEnableShotSwallow;
02708     bool                            mKeepCenterCentered;
02709     bool                            mShowRankThreads;
02710     bool                            mMinimapEnabled;
02711     bool                            mHasReturnQuery;
02712 
02713     ULONG                           mBackNormal;
02714 
02715 public:
02716     static const int MODE_CROSSBROWSER  = 1;
02717     static const int MODE_ROTORBROWSER  = 2;
02718     static const int MODE_FORKBROWSER   = 3;
02719 
02720     static const int STILLS_NONE        = 1;
02721     static const int STILLS_CENTER      = 2;
02722     static const int STILLS_NEARCENTER  = 3;
02723     static const int STILLS_ACTIVE      = 4;
02724     static const int STILLS_ALL         = 5;
02725 
02726     ILOG_VAR_DEC;
02727 
02728 }; // class RotorBrowser
02729 
02730 ILOG_VAR_INIT(RotorBrowser, Visualization.RotorBrowser);
02731 
02732 } // namespace RotorBrowser
02733 } // namespace Visualization
02734 } // namespace Impala
02735 #endif
02736 

Generated on Fri Mar 19 09:31:52 2010 for ImpalaSrc by  doxygen 1.5.1