diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 16 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 17 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 5 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 19 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 15 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.mm | 3 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 50 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.h | 12 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.cpp | 210 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.h | 11 |
10 files changed, 348 insertions, 10 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 220e7aab8cd..5e0216c0339 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -66,6 +66,21 @@ extern GHOST_SystemHandle GHOST_CreateSystem(void); extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle); /** + * Show a system message box to the user + * \param systemhandle The handle to the system + * \param title Title of the message box + * \param message Message of the message box + * \param link Optional (hyper)link to a webpage to show when pressing help + * \param dialog_options Options to configure the message box. + * \return void. + */ +extern void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle, + const char *title, + const char *message, + const char *link, + GHOST_DialogOptions dialog_options); + +/** * Creates an event consumer object * \param eventCallback The event callback routine. * \param userdata Pointer to user data returned to the callback routine. @@ -191,6 +206,7 @@ extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhand * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. * \param systemhandle The handle to the system + * \param platform_support_callback An optional callback to check platform support * \return A handle to the new context ( == NULL if creation failed). */ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle); diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 1eeb6cd852f..d89785ad9b2 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -437,6 +437,23 @@ class GHOST_ISystem { */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; + /*************************************************************************************** + * System Message Box. + ***************************************************************************************/ + + /** + * Show a system message box + * + * \param title The title of the message box + * \param message The message to display + * \param link An optional hyperlink + * \param dialog_options Options how to display the message + */ + virtual GHOST_TSuccess showMessageBox(const char * /*title*/, + const char * /*message*/, + const char * /*link*/, + GHOST_DialogOptions /*dialog_options*/) const = 0; + protected: /** * Initialize the system. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 891f9d982b9..32472373b17 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -58,6 +58,11 @@ typedef enum { GHOST_glAlphaBackground = (1 << 2), } GHOST_GLFlags; +typedef enum GHOST_DialogOptions { + GHOST_DialogWarning = (1 << 0), + GHOST_DialogError = (1 << 1), +} GHOST_DialogOptions; + #ifdef _MSC_VER typedef __int64 GHOST_TInt64; typedef unsigned __int64 GHOST_TUns64; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index d907c10570c..4d755de77ff 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -47,6 +47,16 @@ GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle) return system->disposeSystem(); } +void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle, + const char *title, + const char *message, + const char *link, + GHOST_DialogOptions dialog_options) +{ + GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; + system->showMessageBox(title, message, link, dialog_options); +} + GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata) { @@ -651,8 +661,13 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle) { GHOST_IContext *context = (GHOST_IContext *)contexthandle; - - return context->activateDrawingContext(); + if (context) { + return context->activateDrawingContext(); + } + else { + GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid"); + return GHOST_kFailure; + } } GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle) diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 2e45592e055..ea85611870a 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -309,6 +309,21 @@ class GHOST_System : public GHOST_ISystem { */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; + /** + * Show a system message box + * \param title The title of the message box + * \param message The message to display + * \param link An optional hyperlink + * \param dialog_options Options how to display the message + */ + virtual GHOST_TSuccess showMessageBox(const char * /*title*/, + const char * /*message*/, + const char * /*link*/, + GHOST_DialogOptions /*dialog_options*/) const + { + return GHOST_kFailure; + }; + protected: /** * Initialize the system. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 68bac7d153b..5902abf8382 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1383,7 +1383,8 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) // Check open windows if some changes are not saved if (m_windowManager->getAnyModifiedState()) { - @autoreleasepool { + @autoreleasepool + { NSAlert *alert = [[NSAlert alloc] init]; NSString *title = [NSString stringWithFormat:@"Opening %@", [filepath lastPathComponent]]; NSString *text = @"Current document has not been saved.\nDo you really want to proceed?"; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 1b04e1fde79..1423e0df8ec 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -31,6 +31,7 @@ #include <shlobj.h> #include <tlhelp32.h> #include <psapi.h> +#include <shellapi.h> #include <windowsx.h> #include "utfconv.h" @@ -358,14 +359,8 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext() goto finished; } else { - MessageBox(NULL, - "A graphics card and driver with support for OpenGL 3.3 or higher is required.\n" - "Installing the latest driver for your graphics card may resolve the issue.\n\n" - "The program will now close.", - "Blender - Unsupported Graphics Card or Driver", - MB_OK | MB_ICONERROR); delete context; - exit(); + return NULL; } #elif defined(WITH_GL_PROFILE_COMPAT) @@ -1776,6 +1771,47 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const } } +/** \name Message Box + * \{ */ +static const char *MESSAGE_BOX_HELP_LINK_PTR = NULL; +VOID CALLBACK showMessageBoxCallBack(LPHELPINFO lpHelpInfo) +{ + if (MESSAGE_BOX_HELP_LINK_PTR) { + ShellExecute(NULL, "open", MESSAGE_BOX_HELP_LINK_PTR, NULL, NULL, SW_SHOWNORMAL); + } +} + +GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title, + const char *message, + const char *link, + GHOST_DialogOptions dialog_options) const +{ + uint style = MB_OK | + (dialog_options & GHOST_DialogError ? + MB_ICONERROR : + dialog_options & GHOST_DialogWarning ? MB_ICONWARNING : MB_ICONINFORMATION); + bool show_help = link && strlen(link); + if (show_help) { + GHOST_ASSERT(MESSAGE_BOX_HELP_LINK_PTR == NULL, + "showMessageBox: MESSAGE_BOX_HELP_LINK_PTR is in use"); + style |= MB_HELP; + MESSAGE_BOX_HELP_LINK_PTR = link; + } + + MSGBOXPARAMSA message_box_params = {0}; + message_box_params.cbSize = sizeof(MSGBOXCALLBACK); + message_box_params.lpszText = message; + message_box_params.lpszCaption = title; + message_box_params.dwStyle = style; + message_box_params.lpszText = message; + message_box_params.lpfnMsgBoxCallback = showMessageBoxCallBack; + + MessageBoxIndirectA(&message_box_params); + MESSAGE_BOX_HELP_LINK_PTR = NULL; + return GHOST_kSuccess; +} +/* \} */ + static DWORD GetParentProcessID(void) { HANDLE snapshot; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index a92dea84d70..6e803b3d760 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -205,6 +205,18 @@ class GHOST_SystemWin32 : public GHOST_System { void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** + * Show a system message box + * \param title The title of the message box + * \param message The message to display + * \param link An optional hyperlink + * \param dialog_options Options how to display the message + */ + GHOST_TSuccess showMessageBox(const char *title, + const char *message, + const char *link, + GHOST_DialogOptions dialog_options) const; + + /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. * Called by GHOST_DropTargetWin32 class. * \param eventType: The type of drag'n'drop event diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index a9435f3faff..a6c6aaffd6f 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -2145,6 +2145,216 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const } } +/** \name Message Box + * \{ */ +class DialogData { + public: + /* Width of the dialog */ + uint width; + /* Heigth of the dialog */ + uint height; + /* Default padding (x direction) between controls and edge of dialog */ + uint padding_x; + /* Default padding (y direction) between controls and edge of dialog */ + uint padding_y; + /* Width of a single button */ + uint button_width; + /* Height of a single button */ + uint button_height; + /* Inset of a button to its text */ + uint button_inset_x; + /* Size of the border of the button */ + uint button_border_size; + /* Height of a line of text */ + uint line_height; + /* offset of the text inside the button */ + uint button_text_offset_y; + + /* Construct a new DialogData with the default settings */ + DialogData() + : width(640), + height(175), + padding_x(10), + padding_y(5), + button_width(50), + button_height(24), + button_inset_x(10), + button_border_size(1), + line_height(16) + { + button_text_offset_y = button_height - line_height; + } + + void drawButton(Display *display, + Window &window, + GC &borderGC, + GC &buttonGC, + uint button_num, + const char *label) + { + XFillRectangle(display, + window, + borderGC, + width - (padding_x + button_width) * button_num, + height - padding_y - button_height, + button_width, + button_height); + + XFillRectangle(display, + window, + buttonGC, + width - (padding_x + button_width) * button_num + button_border_size, + height - padding_y - button_height + button_border_size, + button_width - button_border_size * 2, + button_height - button_border_size * 2); + + XDrawString(display, + window, + borderGC, + width - (padding_x + button_width) * button_num + button_inset_x, + height - padding_y - button_text_offset_y, + label, + strlen(label)); + } + + /* Is the mouse inside the given button */ + bool isInsideButton(XEvent &e, uint button_num) + { + return ((e.xmotion.y > height - padding_y - button_height) && + (e.xmotion.y < height - padding_y) && + (e.xmotion.x > width - (padding_x + button_width) * button_num) && + (e.xmotion.x < width - padding_x - (padding_x + button_width) * (button_num - 1))); + } +}; + +static void split(const char *text, const char *seps, char ***str, int *count) +{ + char *tok, *data; + int i; + *count = 0; + + data = strdup(text); + for (tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps)) + (*count)++; + free(data); + + data = strdup(text); + *str = (char **)malloc((size_t)(*count) * sizeof(char *)); + for (i = 0, tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps), i++) + (*str)[i] = strdup(tok); + free(data); +} + +GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title, + const char *message, + const char *link, + GHOST_DialogOptions) const +{ + char **text_splitted = NULL; + int textLines = 0; + split(message, "\n", &text_splitted, &textLines); + + DialogData dialog_data; + XSizeHints hints; + + Window window; + XEvent e; + int screen = DefaultScreen(m_display); + window = XCreateSimpleWindow(m_display, + RootWindow(m_display, screen), + 0, + 0, + dialog_data.width, + dialog_data.height, + 1, + BlackPixel(m_display, screen), + WhitePixel(m_display, screen)); + + /* Window Should not be resizable */ + { + hints.flags = PSize | PMinSize | PMaxSize; + hints.min_width = hints.max_width = hints.base_width = dialog_data.width; + hints.min_height = hints.max_height = hints.base_height = dialog_data.height; + XSetWMNormalHints(m_display, window, &hints); + } + + /* Set title */ + { + Atom wm_Name = XInternAtom(m_display, "_NET_WM_NAME", False); + Atom utf8Str = XInternAtom(m_display, "UTF8_STRING", False); + + Atom winType = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE", False); + Atom typeDialog = XInternAtom(m_display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + + XChangeProperty(m_display, + window, + wm_Name, + utf8Str, + 8, + PropModeReplace, + (const unsigned char *)title, + (int)strlen(title)); + + XChangeProperty( + m_display, window, winType, XA_ATOM, 32, PropModeReplace, (unsigned char *)&typeDialog, 1); + } + + /* Create buttons GC */ + XGCValues buttonBorderGCValues; + buttonBorderGCValues.foreground = BlackPixel(m_display, screen); + buttonBorderGCValues.background = WhitePixel(m_display, screen); + XGCValues buttonGCValues; + buttonGCValues.foreground = WhitePixel(m_display, screen); + buttonGCValues.background = BlackPixel(m_display, screen); + + GC buttonBorderGC = XCreateGC(m_display, window, GCForeground, &buttonBorderGCValues); + GC buttonGC = XCreateGC(m_display, window, GCForeground, &buttonGCValues); + + XSelectInput(m_display, window, ExposureMask | ButtonPressMask | ButtonReleaseMask); + XMapWindow(m_display, window); + + while (1) { + XNextEvent(m_display, &e); + if (e.type == Expose) { + for (int i = 0; i < textLines; i++) { + XDrawString(m_display, + window, + DefaultGC(m_display, screen), + dialog_data.padding_x, + dialog_data.padding_x + (i + 1) * dialog_data.line_height, + text_splitted[i], + (int)strlen(text_splitted[i])); + } + dialog_data.drawButton(m_display, window, buttonBorderGC, buttonGC, 1, "Ok"); + if (strlen(link)) { + dialog_data.drawButton(m_display, window, buttonBorderGC, buttonGC, 2, "Help"); + } + } + else if (e.type == ButtonRelease) { + if (dialog_data.isInsideButton(e, 1)) { + break; + } + else if (strlen(link) && dialog_data.isInsideButton(e, 2)) { + string cmd = "xdg-open \"" + string(link) + "\""; + if (system(cmd.c_str()) != 0) { + GHOST_PRINTF("GHOST_SystemX11::showMessageBox: Unable to run system command [%s]", cmd); + } + } + } + } + + for (int i = 0; i < textLines; i++) { + free(text_splitted[i]); + } + free(text_splitted); + + XDestroyWindow(m_display, window); + XFreeGC(m_display, buttonBorderGC); + XFreeGC(m_display, buttonGC); + return GHOST_kSuccess; +} +/* \} */ + #ifdef WITH_XDND GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 6ad2d6decae..ba7371c6ea0 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -233,6 +233,17 @@ class GHOST_SystemX11 : public GHOST_System { */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + /** + * Show a system message box + * \param title The title of the message box + * \param message The message to display + * \param link An optional hyperlink + * \param dialog_options Options how to display the message + */ + GHOST_TSuccess showMessageBox(const char *title, + const char *message, + const char *link, + GHOST_DialogOptions dialog_options) const; #ifdef WITH_XDND /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. |