Progress indicator in the application icon
authorDamien Plisson <damien.plisson@yahoo.fr>
Tue, 1 Jun 2010 20:21:40 +0000 (20:21 +0000)
committerDamien Plisson <damien.plisson@yahoo.fr>
Tue, 1 Jun 2010 20:21:40 +0000 (20:21 +0000)
Displays a global progress indicator in the application icon reflecting the total progress of all running jobs.

Currently fully implemented on OSX (Cocoa).
On other OSes that do not allow to redraw the app icon, this can be implemented as a [x%] display in the app title, so to appear in the taskbar.

Thanks to Matt for the windowmanager wrapper.

intern/ghost/GHOST_C-api.h
intern/ghost/GHOST_IWindow.h
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_Window.cpp
intern/ghost/intern/GHOST_Window.h
intern/ghost/intern/GHOST_WindowCocoa.h
intern/ghost/intern/GHOST_WindowCocoa.mm
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_jobs.c
source/blender/windowmanager/intern/wm_window.c

index 346fa292520b3748ad2ba898d6432d9f4afdb2ff..a5fec1f101c96932853902f65011487dcfe35f9b 100644 (file)
@@ -264,7 +264,24 @@ extern int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
 extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle,
                                                                                          GHOST_EventConsumerHandle consumerhandle);
        
+/***************************************************************************************
+ ** Progress bar functionality
+ ***************************************************************************************/
+
+/**
+ * Sets the progress bar value displayed in the window/application icon
+ * @param windowhandle The handle to the window
+ * @param progress The progress % (0.0 to 1.0)
+ */
+extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, float progress);
 
+/**
+ * Hides the progress bar in the icon
+ * @param windowhandle The handle to the window
+ */
+extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
+       
+       
 /***************************************************************************************
  ** N-degree of freedom device management functionality
  ***************************************************************************************/
index a024b2b51e5df0dd64a86c93f250fa4a4e6aa90d..83757b17e8b916a03654bb82b19506c8df216fd9 100644 (file)
@@ -234,6 +234,21 @@ public:
         */
        virtual const GHOST_TabletData* GetTabletData() = 0;
        
+       /***************************************************************************************
+        ** Progress bar functionality
+        ***************************************************************************************/
+       
+       /**
+     * Sets the progress bar value displayed in the window/application icon
+        * @param progress The progress %
+        */
+       virtual GHOST_TSuccess setProgressBar(float progress) = 0;
+       
+       /**
+        * Hides the progress bar in the icon
+        */
+       virtual GHOST_TSuccess endProgressBar() = 0;
+       
        /***************************************************************************************
         ** Cursor management functionality
         ***************************************************************************************/
index 44b361d21e4eb2005dab2e46daf92adffc157b83..9da20200f63bc1a9e226fc9ea679afe501325d53 100644 (file)
@@ -248,6 +248,21 @@ GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, GHOST_Eve
        return system->addEventConsumer((GHOST_CallbackEventConsumer*)consumerhandle);
 }
 
+GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle,float progress)
+{
+       GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+       return window->setProgressBar(progress);
+}
+
+GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle)
+{
+       GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
+
+       return window->endProgressBar();
+}
+
+
 int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle,
    GHOST_NDOFLibraryInit_fp setNdofLibraryInit, 
     GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
index e1d0d40e22571f632cc261a78dbf90a2ba031756..374b620c3486b5063c45d338eacb188a3182b8b8 100644 (file)
@@ -53,6 +53,8 @@ GHOST_Window::GHOST_Window(
        m_isUnsavedChanges = false;
        m_canAcceptDragOperation = false;
        
+       m_progressBarVisible = false;
+       
     m_cursorGrabAccumPos[0] = 0;
     m_cursorGrabAccumPos[1] = 0;
 
index bec9cecc830964751b1b712dba1142f8fa61d434..d4d537873570c8e3cf0447c3145520d37141dbfa 100644 (file)
@@ -191,6 +191,17 @@ public:
         */
        virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
 
+       /**
+     * Sets the progress bar value displayed in the window/application icon
+        * @param progress The progress % (0.0 to 1.0)
+        */
+       virtual GHOST_TSuccess setProgressBar(float progress) {return GHOST_kFailure;};
+       
+       /**
+        * Hides the progress bar in the icon
+        */
+       virtual GHOST_TSuccess endProgressBar() {return GHOST_kFailure;};
+       
        /**
         * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
         */
@@ -313,6 +324,9 @@ protected:
        /** The current shape of the cursor */
        GHOST_TStandardCursor m_cursorShape;
     
+       /** The presence of progress indicator with the application icon */
+       bool m_progressBarVisible;
+       
        /** The acceptance of the "drop candidate" of the current drag'n'drop operation */
        bool m_canAcceptDragOperation;
        
index cb27ee4e83eaf3c85903a1955edf5d6d1fe967f8..7948e88e1ab70b3304e1d6a99730f631e72fead4 100644 (file)
@@ -226,6 +226,17 @@ public:
 
        GHOST_TabletData& GetCocoaTabletData()
        { return m_tablet; }
+       
+       /**
+        * Sets the progress bar value displayed in the window/application icon
+        * @param progress The progress % (0.0 to 1.0)
+        */
+       virtual GHOST_TSuccess setProgressBar(float progress);
+       
+       /**
+        * Hides the progress bar icon
+        */
+       virtual GHOST_TSuccess endProgressBar();
 protected:
        /**
         * Tries to install a rendering context in this window.
@@ -291,14 +302,6 @@ protected:
        NSCursor*       m_customCursor;
 
        GHOST_TabletData m_tablet;
-    
-    /**
-     * The width/height of the size rectangle in the lower right corner of a 
-     * Mac/Carbon window. This is also the height of the gutter area.
-     */
-#ifdef GHOST_DRAW_CARBON_GUTTER
-    static const GHOST_TInt32 s_sizeRectSize;
-#endif // GHOST_DRAW_CARBON_GUTTER
 };
 
 #endif // _GHOST_WINDOW_COCOA_H_
index 6dc2fa5a745948b2dc2f9cc49aa16b727347c142..abcb8bcd5ccef1ea27f4163edcc8ce28d49f983c 100644 (file)
@@ -1020,6 +1020,66 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate()
        return GHOST_kSuccess;
 }
 
+#pragma mark Progress bar
+
+GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
+{
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       if ((progress >=0.0) && (progress <=1.0)) {
+               NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
+               
+               [dockIcon lockFocus];
+        NSRect progressBox = {{4, 4}, {120, 16}};
+
+        [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
+        
+        // Track & Outline
+        [[NSColor blackColor] setFill];
+        NSRectFill(progressBox);
+        
+        [[NSColor whiteColor] set];
+        NSFrameRect(progressBox);
+        
+        // Progress fill
+        progressBox = NSInsetRect(progressBox, 1, 1);
+        [[NSColor knobColor] setFill];
+        progressBox.size.width = progressBox.size.width * progress;
+               NSRectFill(progressBox);
+               
+               [dockIcon unlockFocus];
+               
+               [NSApp setApplicationIconImage:dockIcon];
+               [dockIcon release];
+               
+               m_progressBarVisible = true;
+       }
+       
+       [pool drain];
+       return GHOST_kSuccess;
+}
+
+
+GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
+{
+       if (!m_progressBarVisible) return GHOST_kFailure;
+       m_progressBarVisible = false;
+       
+       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+       
+       NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
+       [dockIcon lockFocus];
+       [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
+       [dockIcon unlockFocus];
+       [NSApp setApplicationIconImage:dockIcon];
+       [dockIcon release];
+       
+       [pool drain];
+       return GHOST_kSuccess;
+}
+
+
+
 #pragma mark Cursor handling
 
 void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
index 40186f40e9d1e44ac4c0161a9920be108e19ad49..2b159daf6a149cb0157a9ebad0066364298df501 100644 (file)
@@ -324,5 +324,9 @@ void                WM_jobs_stop_all(struct wmWindowManager *wm);
 char           *WM_clipboard_text_get(int selection);
 void           WM_clipboard_text_set(char *buf, int selection);
 
+                       /* progress */
+void           WM_progress_set(struct wmWindow *win, float progress);
+void           WM_progress_clear(struct wmWindow *win);
+
 #endif /* WM_API_H */
 
index a92a3d746ad97f661db4b93725380b372277cead..e7df703ba793b807daa470213e7f5ff2733e1c58 100644 (file)
@@ -381,6 +381,9 @@ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt)
 void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
 {
        wmJob *steve= wm->jobs.first, *stevenext;
+       float total_progress= 0.f;
+       float jobs_progress=0;
+       
        
        for(; steve; steve= stevenext) {
                stevenext= steve->next;
@@ -434,6 +437,10 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
                                                BLI_remlink(&wm->jobs, steve);
                                                MEM_freeN(steve);
                                        }
+                               } else if (steve->flag & WM_JOB_PROGRESS) {
+                                       /* accumulate global progress for running jobs */
+                                       jobs_progress++;
+                                       total_progress += steve->progress;
                                }
                        }
                        else if(steve->suspended) {
@@ -441,5 +448,13 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
                        }
                }
        }
+       
+       /* if there are running jobs, set the global progress indicator */
+       if (jobs_progress > 0) {
+               float progress = total_progress / (float)jobs_progress;
+               WM_progress_set(wm->winactive, progress);
+       } else {
+               WM_progress_clear(wm->winactive);
+       }
 }
 
index b4270aa9a94a529376ed4878759fdb23b7005679..b730d1a6483c9d9eb3a543af6fdc98e684cd768b 100644 (file)
@@ -1018,6 +1018,18 @@ void WM_clipboard_text_set(char *buf, int selection)
 #endif
 }
 
+/* ******************* progress bar **************** */
+
+void WM_progress_set(wmWindow *win, float progress)
+{
+       GHOST_SetProgressBar(win->ghostwin, progress);
+}
+
+void WM_progress_clear(wmWindow *win)
+{
+       GHOST_EndProgressBar(win->ghostwin);
+}
+
 /* ************************************ */
 
 void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r)