Move some base UI logic to handle the main display from modules/gui.cpp to she library.

This commit is contained in:
David Capello 2012-08-05 21:16:16 -03:00
parent f5ad8c86d3
commit 89cb9d098c
17 changed files with 550 additions and 406 deletions

View File

@ -28,13 +28,15 @@
#include "console.h"
#include "document_wrappers.h"
#include "drop_files.h"
#include "gfxmode.h"
#include "ini_file.h"
#include "modules/editors.h"
#include "modules/gfx.h"
#include "modules/gui.h"
#include "modules/palettes.h"
#include "raster/sprite.h"
#include "she/display.h"
#include "she/surface.h"
#include "she/system.h"
#include "skin/button_icon_impl.h"
#include "skin/skin_property.h"
#include "skin/skin_theme.h"
@ -60,9 +62,6 @@
#include <winalleg.h>
#endif
#define REFRESH_FULL_SCREEN 1
#define SYSTEM_WINDOW_RESIZE 2
#define SPRITEDITOR_ACTION_COPYSELECTION "CopySelection"
#define SPRITEDITOR_ACTION_SNAPTOGRID "SnapToGrid"
#define SPRITEDITOR_ACTION_ANGLESNAP "AngleSnap"
@ -88,8 +87,6 @@ static struct
static int try_depths[] = { 32, 24, 16, 15 };
static GfxMode lastWorkingGfxMode;
//////////////////////////////////////////////////////////////////////
enum ShortcutType { Shortcut_ExecuteCommand,
@ -141,178 +138,71 @@ static Theme* ase_theme = NULL;
static std::vector<Shortcut*>* shortcuts = NULL;
static bool ji_screen_created = false;
static volatile int next_idle_flags = 0;
static volatile int restored_width = 0;
static volatile int restored_height = 0;
// Default GUI screen configuration
static bool double_buffering;
static int screen_scaling;
static void reload_default_font();
// Load & save graphics configuration
static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized);
static void load_gui_config(int& w, int& h, bool& maximized);
static void save_gui_config();
static bool button_with_icon_msg_proc(Widget* widget, Message* msg);
static void on_palette_change_signal();
// Used by set_display_switch_callback(SWITCH_IN, ...).
static void display_switch_in_callback()
{
next_idle_flags |= REFRESH_FULL_SCREEN;
}
END_OF_STATIC_FUNCTION(display_switch_in_callback);
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
// Called when the window is resized
static void resize_callback(RESIZE_DISPLAY_EVENT *ev)
{
if (ev->is_maximized) {
restored_width = ev->old_w;
restored_height = ev->old_h;
}
next_idle_flags |= SYSTEM_WINDOW_RESIZE;
}
#endif // ALLEGRO4_WITH_RESIZE_PATCH
// Initializes GUI.
int init_module_gui()
{
int min_possible_dsk_res = 0;
int c, w, h, bpp, autodetect;
bool fullscreen;
int c, w, h, min_possible_dsk_res = 0;
bool maximized;
shortcuts = new std::vector<Shortcut*>;
// Install the mouse
if (install_mouse() < 0)
throw base::Exception("Error installing mouse handler");
// Install the keyboard
if (install_keyboard() < 0)
throw base::Exception("Error installing keyboard handler");
// Disable Ctrl+Shift+End in non-DOS
#if !defined(ALLEGRO_DOS)
three_finger_flag = false;
#endif
three_finger_flag = true; // TODO remove this line
// Set the graphics mode...
load_gui_config(w, h, bpp, fullscreen, maximized);
load_gui_config(w, h, maximized);
autodetect = fullscreen ? GFX_AUTODETECT_FULLSCREEN:
GFX_AUTODETECT_WINDOWED;
// Default resolution
if (!w || !h) {
bool has_desktop = false;
int dsk_w, dsk_h;
has_desktop = get_desktop_resolution(&dsk_w, &dsk_h) == 0;
#ifndef FULLSCREEN_PLATFORM
// We must extract some space for the windows borders
dsk_w -= 16;
dsk_h -= 32;
#endif
// Try to get desktop resolution
if (has_desktop) {
for (c=0; try_resolutions[c].width; ++c) {
if (try_resolutions[c].width <= dsk_w &&
try_resolutions[c].height <= dsk_h) {
min_possible_dsk_res = c;
fullscreen = false;
w = try_resolutions[c].width;
h = try_resolutions[c].height;
screen_scaling = try_resolutions[c].scale;
break;
}
}
}
// Full screen
else {
fullscreen = true;
w = 320;
h = 200;
screen_scaling = 1;
}
she::Display* display = NULL;
try {
display = she::Instance()->createDisplay(w, h, screen_scaling);
}
// Default color depth
if (!bpp) {
bpp = desktop_color_depth();
if (!bpp)
bpp = 16;
}
for (;;) {
if (bpp == 8)
throw base::Exception("You cannot use ASEPRITE in 8 bits per pixel");
// Original
set_color_depth(bpp);
if (set_gfx_mode(autodetect, w, h, 0, 0) == 0)
break;
catch (const she::DisplayCreationException&) {
for (c=min_possible_dsk_res; try_resolutions[c].width; ++c) {
if (set_gfx_mode(autodetect,
try_resolutions[c].width,
try_resolutions[c].height, 0, 0) == 0) {
try {
display = she::Instance()->createDisplay(try_resolutions[c].width,
try_resolutions[c].height,
try_resolutions[c].scale);
screen_scaling = try_resolutions[c].scale;
goto gfx_done;
}
}
if (bpp == 15)
throw base::Exception("Error setting graphics mode\n%s\n"
"Try \"ase -res WIDTHxHEIGHTxBPP\"\n", allegro_error);
for (c=0; try_depths[c]; ++c) {
if (bpp == try_depths[c]) {
bpp = try_depths[c+1];
break;
}
catch (const she::DisplayCreationException&) {
// Ignore
}
}
}
gfx_done:;
if (!display) {
allegro_message("Unable to create a user-interface display.\n");
return -1;
}
// Create the default-manager
manager = new CustomizedGuiManager();
manager->setDisplay(display);
// Setup the GUI theme for all widgets
CurrentTheme::set(ase_theme = new SkinTheme());
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
// Setup the handler for window-resize events
set_resize_callback(resize_callback);
#endif
#ifdef ALLEGRO_WINDOWS
if (maximized) {
ShowWindow(win_get_window(), SW_MAXIMIZE);
}
#endif
if (maximized)
display->maximize();
// Configure ji_screen
gui_setup_screen(true);
// Add a hook to display-switch so when the user returns to the
// screen it's completelly refreshed/redrawn.
LOCK_VARIABLE(next_idle_flags);
LOCK_FUNCTION(display_switch_in_callback);
set_display_switch_callback(SWITCH_IN, display_switch_in_callback);
// Set graphics options for next time
save_gui_config();
@ -334,15 +224,6 @@ void exit_module_gui()
delete shortcuts;
shortcuts = NULL;
if (double_buffering) {
BITMAP *old_bmp = ji_screen;
ji_set_screen(screen, SCREEN_W, SCREEN_H);
if (ji_screen_created)
destroy_bitmap(old_bmp);
ji_screen_created = false;
}
delete manager;
// Now we can destroy theme
@ -353,46 +234,24 @@ void exit_module_gui()
remove_mouse();
}
static void load_gui_config(int& w, int& h, int& bpp, bool& fullscreen, bool& maximized)
static void load_gui_config(int& w, int& h, bool& maximized)
{
w = get_config_int("GfxMode", "Width", 0);
h = get_config_int("GfxMode", "Height", 0);
bpp = get_config_int("GfxMode", "Depth", 0);
fullscreen = get_config_bool("GfxMode", "FullScreen",
#ifdef FULLSCREEN_PLATFORM
true
#else
false
#endif
);
screen_scaling = get_config_int("GfxMode", "ScreenScale", 2);
screen_scaling = MID(1, screen_scaling, 4);
maximized = get_config_bool("GfxMode", "Maximized", false);
// Avoid 8 bpp
if (bpp == 8)
bpp = 32;
}
static void save_gui_config()
{
bool is_maximized = false;
#ifdef WIN32
is_maximized = (GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
#endif
set_config_bool("GfxMode", "Maximized", is_maximized);
if (screen) {
set_config_int("GfxMode", "Width", is_maximized ? restored_width: SCREEN_W);
set_config_int("GfxMode", "Height", is_maximized ? restored_height: SCREEN_H);
she::Display* display = Manager::getDefault()->getDisplay();
if (display) {
set_config_bool("GfxMode", "Maximized", display->isMaximized());
set_config_int("GfxMode", "Width", display->originalWidth());
set_config_int("GfxMode", "Height", display->originalHeight());
set_config_int("GfxMode", "Depth", bitmap_color_depth(screen));
}
if (gfx_driver)
set_config_bool("GfxMode", "FullScreen", gfx_driver->windowed ? false: true);
set_config_int("GfxMode", "ScreenScale", screen_scaling);
}
@ -443,70 +302,14 @@ void gui_run()
void gui_feedback()
{
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
if (next_idle_flags & SYSTEM_WINDOW_RESIZE) {
next_idle_flags ^= SYSTEM_WINDOW_RESIZE;
if (acknowledge_resize() < 0)
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 320, 240, 0, 0);
jmouse_draw_cursor();
if (!Manager::getDefault()->getDisplay()->flip()) {
// In case that the display was resized.
gui_setup_screen(false);
App::instance()->getMainWindow()->remap_window();
Manager::getDefault()->invalidate();
}
#endif
if (next_idle_flags & REFRESH_FULL_SCREEN) {
next_idle_flags ^= REFRESH_FULL_SCREEN;
try {
const ActiveDocumentReader document(UIContext::instance());
update_screen_for_document(document);
}
catch (...) {
// do nothing
}
}
gui_flip_screen();
}
void gui_flip_screen()
{
// Double buffering?
if (double_buffering && ji_screen && screen) {
jmouse_draw_cursor();
if (ji_dirty_region) {
ji_flip_dirty_region();
}
else {
if (JI_SCREEN_W == SCREEN_W && JI_SCREEN_H == SCREEN_H) {
blit(ji_screen, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}
else {
stretch_blit(ji_screen, screen,
0, 0, JI_SCREEN_W, JI_SCREEN_H,
0, 0, SCREEN_W, SCREEN_H);
}
}
}
// This is a strange Allegro bug where the "screen" pointer is lost,
// so we have to reconstruct it changing the gfx mode again
else if (screen == NULL) {
PRINTF("Gfx mode lost, trying to restore gfx mode...\n");
if (!lastWorkingGfxMode.setGfxMode()) {
PRINTF("Fatal error\n");
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("FATAL ERROR: Unable to restore the old graphics mode!\n");
exit(1);
}
PRINTF("Successfully restored\n");
}
else
lastWorkingGfxMode.updateWithCurrentMode();
}
// Sets the ji_screen variable. This routine should be called
@ -516,27 +319,8 @@ void gui_setup_screen(bool reload_font)
bool regen = false;
bool reinit = false;
// Double buffering is required when screen scaling is used
double_buffering = (screen_scaling > 1);
// Is double buffering active?
if (double_buffering) {
BITMAP *old_bmp = ji_screen;
int new_w = SCREEN_W / screen_scaling;
int new_h = SCREEN_H / screen_scaling;
BITMAP *new_bmp = create_bitmap(new_w, new_h);
ji_set_screen(new_bmp, new_w, new_h);
if (ji_screen_created)
destroy_bitmap(old_bmp);
ji_screen_created = true;
}
else {
ji_set_screen(screen, SCREEN_W, SCREEN_H);
ji_screen_created = false;
}
Manager::getDefault()->getDisplay()->setScale(screen_scaling);
ui::SetDisplay(Manager::getDefault()->getDisplay());
// Update guiscale factor
int old_guiscale = jguiscale();

View File

@ -51,7 +51,6 @@ void update_screen_for_document(const Document* document);
void gui_run();
void gui_feedback();
void gui_flip_screen();
void gui_setup_screen(bool reload_font);
void load_window_pos(ui::Widget* window, const char *section);

20
src/she/capabilities.h Normal file
View File

@ -0,0 +1,20 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_CAPABILITIES_H_INCLUDED
#define SHE_CAPABILITIES_H_INCLUDED
namespace she {
enum Capabilities {
kMultipleDisplaysCapability = 1,
kCanResizeDisplayCapability = 2,
kDisplayScaleCapability = 4
};
} // namespace she
#endif

50
src/she/display.h Normal file
View File

@ -0,0 +1,50 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_DISPLAY_H_INCLUDED
#define SHE_DISPLAY_H_INCLUDED
namespace she {
class Surface;
// A display or window to show graphics.
class Display {
public:
virtual ~Display() { }
virtual void dispose() = 0;
// Returns the real and current display's size (without scale applied).
virtual int width() const = 0;
virtual int height() const = 0;
// Returns the display when it was not maximized.
virtual int originalWidth() const = 0;
virtual int originalHeight() const = 0;
// Changes the scale (each pixel will be SCALExSCALE in the screen).
// The available surface size will be (Display::width() / scale,
// Display::height() / scale)
virtual void setScale(int scale) = 0;
// Returns the main surface to draw into this display.
virtual Surface* getSurface() = 0;
// Flips all graphics in the surface to the real display. Returns
// false if the flip couldn't be done because the display was
// resized.
virtual bool flip() = 0;
virtual void maximize() = 0;
virtual bool isMaximized() const = 0;
// Returns the HWND on Windows.
virtual void* nativeHandle() = 0;
};
} // namespace she
#endif

22
src/she/locked_surface.h Normal file
View File

@ -0,0 +1,22 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_LOCKED_SURFACE_H_INCLUDED
#define SHE_LOCKED_SURFACE_H_INCLUDED
namespace she {
class LockedSurface {
public:
virtual ~LockedSurface() { }
virtual void unlock() = 0;
virtual void clear() = 0;
virtual void blitTo(LockedSurface* dest, int x, int y) const = 0;
};
} // namespace she
#endif

30
src/she/scoped_handle.h Normal file
View File

@ -0,0 +1,30 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_SCOPED_HANDLE_H_INCLUDED
#define SHE_SCOPED_HANDLE_H_INCLUDED
namespace she {
template<typename T>
class ScopedHandle {
public:
ScopedHandle(T* handle) : m_handle(handle) { }
~ScopedHandle() { m_handle->dispose(); }
T* operator->() { return m_handle; }
operator T*() { return m_handle; }
private:
T* m_handle;
// Cannot copy
ScopedHandle(const ScopedHandle&);
ScopedHandle& operator=(const ScopedHandle&);
};
} // namespace she
#endif

View File

@ -0,0 +1,28 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
#define SHE_SCOPED_SURFACE_LOCK_H_INCLUDED
#include "she/surface.h"
#include "she/locked_surface.h"
namespace she {
class ScopedSurfaceLock {
public:
ScopedSurfaceLock(Surface* surface) : m_lock(surface->lock()) { }
~ScopedSurfaceLock() { m_lock->unlock(); }
LockedSurface* operator->() { return m_lock; }
operator LockedSurface*() { return m_lock; }
private:
LockedSurface* m_lock;
};
} // namespace she
#endif

View File

@ -7,29 +7,11 @@
#ifndef SHE_H_INCLUDED
#define SHE_H_INCLUDED
namespace she {
class System {
public:
virtual ~System() { }
virtual void dispose() = 0;
};
System* CreateSystem();
template<typename T>
class ScopedHandle {
public:
ScopedHandle(T* handle) : m_handle(handle) { }
~ScopedHandle() { m_handle->dispose(); }
private:
T* m_handle;
// Cannot copy
ScopedHandle(const ScopedHandle&);
ScopedHandle& operator=(const ScopedHandle&);
};
} // namespace she
#include "she/display.h"
#include "she/locked_surface.h"
#include "she/scoped_handle.h"
#include "she/scoped_surface_lock.h"
#include "she/surface.h"
#include "she/system.h"
#endif

View File

@ -11,12 +11,246 @@
#include "she.h"
#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif
#include "loadpng.h"
#include <cassert>
#define DISPLAY_FLAG_FULL_REFRESH 1
#define DISPLAY_FLAG_WINDOW_RESIZE 2
static volatile int display_flags = 0;
static volatile int original_width = 0;
static volatile int original_height = 0;
// Used by set_display_switch_callback(SWITCH_IN, ...).
static void display_switch_in_callback()
{
display_flags |= DISPLAY_FLAG_FULL_REFRESH;
}
END_OF_STATIC_FUNCTION(display_switch_in_callback);
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
// Called when the window is resized
static void resize_callback(RESIZE_DISPLAY_EVENT* ev)
{
if (ev->is_maximized) {
original_width = ev->old_w;
original_height = ev->old_h;
}
display_flags |= DISPLAY_FLAG_WINDOW_RESIZE;
}
#endif // ALLEGRO4_WITH_RESIZE_PATCH
namespace she {
class Alleg4Surface : public Surface
, public LockedSurface {
public:
Alleg4Surface(BITMAP* bmp)
: m_bmp(bmp)
, m_destroy(false)
{
}
Alleg4Surface(int width, int height)
: m_bmp(create_bitmap(width, height))
, m_destroy(true)
{
}
~Alleg4Surface() {
if (m_destroy)
destroy_bitmap(m_bmp);
}
// Surface implementation
void dispose() {
delete this;
}
int width() const {
return m_bmp->w;
}
int height() const {
return m_bmp->h;
}
LockedSurface* lock() {
acquire_bitmap(m_bmp);
return this;
}
void* nativeHandle() {
return reinterpret_cast<void*>(m_bmp);
}
// LockedSurface implementation
void unlock() {
release_bitmap(m_bmp);
}
void clear() {
clear_to_color(m_bmp, 0);
}
void blitTo(LockedSurface* dest, int x, int y) const {
ASSERT(m_bmp);
ASSERT(dest);
ASSERT(static_cast<Alleg4Surface*>(dest)->m_bmp);
blit(m_bmp,
static_cast<Alleg4Surface*>(dest)->m_bmp,
0, 0,
x, y,
m_bmp->w, m_bmp->h);
}
private:
BITMAP* m_bmp;
bool m_destroy;
};
class Alleg4Display : public Display {
public:
Alleg4Display(int width, int height, int scale)
: m_surface(NULL)
, m_scale(0) {
if (install_mouse() < 0) throw DisplayCreationException(allegro_error);
if (install_keyboard() < 0) throw DisplayCreationException(allegro_error);
#ifdef FULLSCREEN_PLATFORM
set_color_depth(16); // TODO Try all color depths for fullscreen platforms
#else
set_color_depth(desktop_color_depth());
#endif
if (set_gfx_mode(
#ifdef FULLSCREEN_PLATFORM
GFX_AUTODETECT_FULLSCREEN,
#else
GFX_AUTODETECT_WINDOWED,
#endif
width, height, 0, 0) < 0)
throw DisplayCreationException(allegro_error);
setScale(scale);
// Add a hook to display-switch so when the user returns to the
// screen it's completelly refreshed/redrawn.
LOCK_VARIABLE(display_flags);
LOCK_FUNCTION(display_switch_in_callback);
set_display_switch_callback(SWITCH_IN, display_switch_in_callback);
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
// Setup the handler for window-resize events
set_resize_callback(resize_callback);
#endif
}
~Alleg4Display() {
m_surface->dispose();
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
}
void dispose() {
delete this;
}
int width() const {
return SCREEN_W;
}
int height() const {
return SCREEN_H;
}
int originalWidth() const {
return original_width > 0 ? original_width: width();
}
int originalHeight() const {
return original_height > 0 ? original_height: height();
}
void setScale(int scale) {
ASSERT(scale >= 1);
if (m_scale == scale)
return;
m_scale = scale;
Surface* newSurface = new Alleg4Surface(SCREEN_W/m_scale,
SCREEN_H/m_scale);
if (m_surface)
m_surface->dispose();
m_surface = newSurface;
}
Surface* getSurface() {
return m_surface;
}
bool flip() {
#ifdef ALLEGRO4_WITH_RESIZE_PATCH
if (display_flags & DISPLAY_FLAG_WINDOW_RESIZE) {
display_flags ^= DISPLAY_FLAG_WINDOW_RESIZE;
acknowledge_resize();
int scale = m_scale;
m_scale = 0;
setScale(scale);
return false;
}
#endif
BITMAP* bmp = reinterpret_cast<BITMAP*>(m_surface->nativeHandle());
if (m_scale == 1) {
blit(bmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}
else {
stretch_blit(bmp, screen,
0, 0, bmp->w, bmp->h,
0, 0, SCREEN_W, SCREEN_H);
}
return true;
}
void maximize() {
#ifdef WIN32
::ShowWindow(win_get_window(), SW_MAXIMIZE);
#endif
}
bool isMaximized() const {
#ifdef WIN32
return (::GetWindowLong(win_get_window(), GWL_STYLE) & WS_MAXIMIZE ? true: false);
#else
return false;
#endif
}
void* nativeHandle() {
#ifdef WIN32
return reinterpret_cast<void*>(win_get_window());
#else
return NULL;
#endif
}
private:
Surface* m_surface;
int m_scale;
};
class Alleg4System : public System {
public:
Alleg4System() {
@ -37,12 +271,31 @@ public:
delete this;
}
Capabilities capabilities() const {
return kCanResizeDisplayCapability;
}
Display* createDisplay(int width, int height, int scale) {
return new Alleg4Display(width, height, scale);
}
Surface* createSurface(int width, int height) {
return new Alleg4Surface(width, height);
}
};
static System* g_instance;
System* CreateSystem() {
return new Alleg4System();
return g_instance = new Alleg4System();
}
System* Instance()
{
return g_instance;
}
}
#ifdef main

26
src/she/surface.h Normal file
View File

@ -0,0 +1,26 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_SURFACE_H_INCLUDED
#define SHE_SURFACE_H_INCLUDED
namespace she {
class LockedSurface;
class Surface {
public:
virtual ~Surface() { }
virtual void dispose() = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual LockedSurface* lock() = 0;
virtual void* nativeHandle() = 0;
};
} // namespace she
#endif

38
src/she/system.h Normal file
View File

@ -0,0 +1,38 @@
// SHE library
// Copyright (C) 2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef SHE_SYSTEM_H_INCLUDED
#define SHE_SYSTEM_H_INCLUDED
#include "she/capabilities.h"
#include <stdexcept>
namespace she {
class Surface;
class Display;
class DisplayCreationException : std::runtime_error {
public:
DisplayCreationException(const char* msg) throw()
: std::runtime_error(msg) { }
};
class System {
public:
virtual ~System() { }
virtual void dispose() = 0;
virtual Capabilities capabilities() const = 0;
virtual Display* createDisplay(int width, int height, int scale) = 0;
virtual Surface* createSurface(int width, int height) = 0;
};
System* CreateSystem();
System* Instance();
} // namespace she
#endif

View File

@ -203,12 +203,6 @@ void ji_move_region(JRegion region, int dx, int dy)
int c, nrects = JI_REGION_NUM_RECTS(region);
JRect rc;
if (ji_dirty_region) {
jregion_translate(region, dx, dy);
ji_add_dirty_region(region);
jregion_translate(region, -dx, -dy);
}
// Blit directly screen to screen.
if (is_linear_bitmap(ji_screen) && nrects == 1) {
rc = JI_REGION_RECTS(region);

View File

@ -112,9 +112,6 @@ Manager::Manager()
: Widget(JI_MANAGER)
{
if (!m_defaultManager) {
if (!ji_screen)
ji_set_screen(screen, SCREEN_W, SCREEN_H);
// Hook the window close message
want_close_stage = STAGE_NORMAL;
set_close_button_callback(allegro_window_close_hook);
@ -1102,10 +1099,6 @@ void Manager::pumpQueue()
if (msg->type == JM_DRAW) {
set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1);
/* dirty rectangles */
if (ji_dirty_region)
ji_add_dirty_rect(&msg->draw.rect);
release_bitmap(ji_screen);
jmouse_show();
}

View File

@ -10,6 +10,8 @@
#include "base/compiler_specific.h"
#include "ui/widget.h"
namespace she { class Display; }
namespace ui {
class LayoutIO;
@ -24,6 +26,9 @@ namespace ui {
Manager();
~Manager();
she::Display* getDisplay() { return m_display; }
void setDisplay(she::Display* display) { m_display = display; }
void run();
// Returns true if there are messages in the queue to be
@ -85,6 +90,7 @@ namespace ui {
static Manager* m_defaultManager;
WidgetsList m_garbage;
she::Display* m_display;
};
} // namespace ui

View File

@ -24,8 +24,8 @@ PaintEvent::~PaintEvent()
Graphics* PaintEvent::getGraphics()
{
// If someone requests the graphics pointer, it means that this
// "someone" will paint something.
// If someone requested the graphics pointer, it means that this
// "someone" has painted the widget.
m_painted = true;
return m_graphics;
}

View File

@ -6,6 +6,17 @@
#include "config.h"
#include "ui/system.h"
#include "she/display.h"
#include "she/surface.h"
#include "ui/intern.h"
#include "ui/manager.h"
#include "ui/rect.h"
#include "ui/region.h"
#include "ui/theme.h"
#include "ui/widget.h"
#include <allegro.h>
#if defined(ALLEGRO_WINDOWS)
#include <winalleg.h>
@ -13,19 +24,11 @@
#include <xalleg.h>
#endif
#include "ui/intern.h"
#include "ui/manager.h"
#include "ui/rect.h"
#include "ui/region.h"
#include "ui/system.h"
#include "ui/theme.h"
#include "ui/widget.h"
namespace ui {
/* Global output bitmap. */
BITMAP *ji_screen = NULL;
BITMAP* ji_screen = NULL;
JRegion ji_dirty_region = NULL;
int ji_screen_w = 0;
int ji_screen_h = 0;
@ -83,9 +86,6 @@ static void set_cursor(BITMAP *bmp, int x, int y)
int _ji_system_init()
{
/* Update screen pointer. */
ji_set_screen(screen, SCREEN_W, SCREEN_H);
/* Install timer related stuff. */
LOCK_VARIABLE(ji_clock);
LOCK_VARIABLE(m_b);
@ -105,103 +105,38 @@ int _ji_system_init()
void _ji_system_exit()
{
ji_set_screen(NULL, 0, 0);
SetDisplay(NULL);
remove_int(clock_inc);
}
void ji_set_screen(BITMAP *bmp, int width, int height)
void SetDisplay(she::Display* display)
{
int cursor = jmouse_get_cursor(); /* get mouse cursor */
int cursor = jmouse_get_cursor();
jmouse_set_cursor(JI_CURSOR_NULL);
ji_screen = bmp;
ji_screen_w = width;
ji_screen_h = height;
ji_screen = (display ? reinterpret_cast<BITMAP*>(display->getSurface()->nativeHandle()): NULL);
ji_screen_w = (ji_screen ? ji_screen->w: 0);
ji_screen_h = (ji_screen ? ji_screen->h: 0);
if (ji_screen != NULL) {
Manager* manager = Manager::getDefault();
if (manager) {
manager->setDisplay(display);
/* update default-manager size */
if (manager && (jrect_w(manager->rc) != JI_SCREEN_W ||
jrect_h(manager->rc) != JI_SCREEN_H)) {
JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H);
jwidget_set_rect(manager, rect);
jrect_free(rect);
if (ji_dirty_region)
jregion_reset(ji_dirty_region, manager->rc);
// Update default-manager size
if ((jrect_w(manager->rc) != JI_SCREEN_W ||
jrect_h(manager->rc) != JI_SCREEN_H)) {
JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H);
jwidget_set_rect(manager, rect);
jrect_free(rect);
}
}
jmouse_set_cursor(cursor); /* restore mouse cursor */
}
}
void ji_add_dirty_rect(JRect rect)
{
JRegion reg1;
ASSERT(ji_dirty_region != NULL);
reg1 = jregion_new(rect, 1);
jregion_union(ji_dirty_region, ji_dirty_region, reg1);
jregion_free(reg1);
}
void ji_add_dirty_region(JRegion region)
{
ASSERT(ji_dirty_region != NULL);
jregion_union(ji_dirty_region, ji_dirty_region, region);
}
void ji_flip_dirty_region()
{
int c, nrects;
JRect rc;
ASSERT(ji_dirty_region != NULL);
nrects = JI_REGION_NUM_RECTS(ji_dirty_region);
if (nrects == 1) {
rc = JI_REGION_RECTS(ji_dirty_region);
ji_flip_rect(rc);
}
else if (nrects > 1) {
for (c=0, rc=JI_REGION_RECTS(ji_dirty_region);
c<nrects;
c++, rc++)
ji_flip_rect(rc);
}
jregion_empty(ji_dirty_region);
}
void ji_flip_rect(JRect rect)
{
ASSERT(ji_screen != screen);
if (JI_SCREEN_W == SCREEN_W && JI_SCREEN_H == SCREEN_H) {
blit(ji_screen, screen,
rect->x1, rect->y1,
rect->x1, rect->y1,
jrect_w(rect),
jrect_h(rect));
}
else {
stretch_blit(ji_screen, screen,
rect->x1,
rect->y1,
jrect_w(rect),
jrect_h(rect),
rect->x1 * SCREEN_W / JI_SCREEN_W,
rect->y1 * SCREEN_H / JI_SCREEN_H,
jrect_w(rect) * SCREEN_W / JI_SCREEN_W,
jrect_h(rect) * SCREEN_H / JI_SCREEN_H);
}
}
int jmouse_get_cursor()
{
return m_cursor;
@ -257,10 +192,6 @@ void jmouse_draw_cursor()
ji_get_default_manager()->invalidateRect(rect);
/* rectfill(ji_screen, rect->x1, rect->y1, rect->x2-1, rect->y2-1, makecol(0, 0, 255)); */
draw_sprite(ji_screen, sprite_cursor, x, y);
if (ji_dirty_region)
ji_add_dirty_rect(rect);
jrect_free(rect);
}
#endif
@ -273,14 +204,6 @@ void jmouse_draw_cursor()
capture_covered_area();
draw_sprite(ji_screen, sprite_cursor, x, y);
if (ji_dirty_region) {
JRect rect = jrect_new(x, y,
x+sprite_cursor->w,
y+sprite_cursor->h);
ji_add_dirty_rect(rect);
jrect_free(rect);
}
}
}

View File

@ -12,6 +12,8 @@
struct BITMAP;
namespace she { class Display; }
namespace ui {
/***********************************************************************/
@ -20,17 +22,11 @@ namespace ui {
#define JI_SCREEN_W ji_screen_w
#define JI_SCREEN_H ji_screen_h
extern struct BITMAP *ji_screen;
extern JRegion ji_dirty_region;
extern struct BITMAP* ji_screen;
extern int ji_screen_w;
extern int ji_screen_h;
void ji_set_screen(BITMAP *bmp, int width, int height);
void ji_add_dirty_rect(JRect rect);
void ji_add_dirty_region(JRegion region);
void ji_flip_dirty_region();
void ji_flip_rect(JRect rect);
void SetDisplay(she::Display* display);
/***********************************************************************/
/* timer related */