mirror of
https://gitee.com/idea4good/GuiLite.git
synced 2025-04-24 00:01:08 +08:00
538 lines
11 KiB
C++
538 lines
11 KiB
C++
#ifndef GUILITE_CORE_INCLUDE_WND_H
|
|
#define GUILITE_CORE_INCLUDE_WND_H
|
|
|
|
#include "../core_include/api.h"
|
|
#include "../core_include/rect.h"
|
|
#include "../core_include/cmd_target.h"
|
|
#include "../core_include/resource.h"
|
|
#include "../core_include/bitmap.h"
|
|
#include "../core_include/display.h"
|
|
|
|
typedef struct struct_font_info FONT_INFO;
|
|
typedef struct struct_color_rect COLOR_RECT;
|
|
|
|
class c_wnd;
|
|
class c_surface;
|
|
|
|
typedef enum
|
|
{
|
|
ATTR_VISIBLE = 0x40000000L,
|
|
ATTR_FOCUS = 0x20000000L,
|
|
ATTR_PRIORITY = 0x10000000L// Handle touch action at high priority
|
|
}WND_ATTRIBUTION;
|
|
|
|
typedef enum
|
|
{
|
|
STATUS_NORMAL,
|
|
STATUS_PUSHED,
|
|
STATUS_FOCUSED,
|
|
STATUS_DISABLED
|
|
}WND_STATUS;
|
|
|
|
typedef enum
|
|
{
|
|
KEY_FORWARD,
|
|
KEY_BACKWARD,
|
|
KEY_ENTER
|
|
}KEY_TYPE;
|
|
|
|
typedef enum
|
|
{
|
|
TOUCH_DOWN,
|
|
TOUCH_UP
|
|
}TOUCH_ACTION;
|
|
|
|
typedef struct struct_wnd_tree
|
|
{
|
|
c_wnd* p_wnd;
|
|
unsigned int resource_id;
|
|
const char* str;
|
|
short x;
|
|
short y;
|
|
short width;
|
|
short height;
|
|
struct struct_wnd_tree* p_child_tree;
|
|
}WND_TREE;
|
|
|
|
class c_wnd : public c_cmd_target
|
|
{
|
|
friend class c_dialog;
|
|
public:
|
|
c_wnd() : m_status(STATUS_NORMAL), m_attr((WND_ATTRIBUTION)(ATTR_VISIBLE | ATTR_FOCUS)), m_parent(0), m_top_child(0), m_prev_sibling(0), m_next_sibling(0),
|
|
m_str(0), m_font_color(0), m_bg_color(0), m_id(0), m_z_order(Z_ORDER_LEVEL_0), m_focus_child(0), m_surface(0) {};
|
|
virtual ~c_wnd() {};
|
|
virtual int connect(c_wnd *parent, unsigned short resource_id, const char* str,
|
|
short x, short y, short width, short height, WND_TREE* p_child_tree = 0)
|
|
{
|
|
if (0 == resource_id)
|
|
{
|
|
ASSERT(false);
|
|
return -1;
|
|
}
|
|
|
|
m_id = resource_id;
|
|
set_str(str);
|
|
m_parent = parent;
|
|
m_status = STATUS_NORMAL;
|
|
|
|
if (parent)
|
|
{
|
|
m_z_order = parent->m_z_order;
|
|
m_surface = parent->m_surface;
|
|
}
|
|
if (0 == m_surface)
|
|
{
|
|
ASSERT(false);
|
|
return -2;
|
|
}
|
|
|
|
/* (cs.x = x * 1024 / 768) for 1027*768=>800*600 quickly*/
|
|
m_wnd_rect.m_left = x;
|
|
m_wnd_rect.m_top = y;
|
|
m_wnd_rect.m_right = (x + width - 1);
|
|
m_wnd_rect.m_bottom = (y + height - 1);
|
|
|
|
pre_create_wnd();
|
|
|
|
if (0 != parent)
|
|
{
|
|
parent->add_child_2_tail(this);
|
|
}
|
|
|
|
if (load_child_wnd(p_child_tree) >= 0)
|
|
{
|
|
load_cmd_msg();
|
|
on_init_children();
|
|
}
|
|
return 0;
|
|
}
|
|
void disconnect()
|
|
{
|
|
if (0 == m_id)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (0 != m_top_child)
|
|
{
|
|
c_wnd* child = m_top_child;
|
|
c_wnd* next_child = 0;
|
|
|
|
while (child)
|
|
{
|
|
next_child = child->m_next_sibling;
|
|
child->disconnect();
|
|
child = next_child;
|
|
}
|
|
}
|
|
|
|
if (0 != m_parent)
|
|
{
|
|
m_parent->unlink_child(this);
|
|
}
|
|
m_focus_child = 0;
|
|
m_id = 0;
|
|
}
|
|
virtual void on_init_children() {}
|
|
virtual void on_paint() {}
|
|
virtual void show_window()
|
|
{
|
|
if (ATTR_VISIBLE == (m_attr & ATTR_VISIBLE))
|
|
{
|
|
on_paint();
|
|
c_wnd* child = m_top_child;
|
|
if (0 != child)
|
|
{
|
|
while (child)
|
|
{
|
|
child->show_window();
|
|
child = child->m_next_sibling;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned short get_id() const { return m_id; }
|
|
int get_z_order() { return m_z_order; }
|
|
c_wnd* get_wnd_ptr(unsigned short id) const
|
|
{
|
|
c_wnd* child = m_top_child;
|
|
|
|
while (child)
|
|
{
|
|
if (child->get_id() == id)
|
|
{
|
|
break;
|
|
}
|
|
|
|
child = child->m_next_sibling;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
unsigned int get_attr() const { return m_attr; }
|
|
|
|
void set_str(const char* str) { m_str = str; }
|
|
void set_attr(WND_ATTRIBUTION attr) { m_attr = attr; }
|
|
bool is_focus_wnd() const
|
|
{
|
|
return ((m_attr & ATTR_VISIBLE) && (m_attr & ATTR_FOCUS)) ? true : false;
|
|
}
|
|
|
|
void set_font_color(unsigned int color) { m_font_color = color; }
|
|
unsigned int get_font_color() { return m_font_color; }
|
|
void set_bg_color(unsigned int color) { m_bg_color = color; }
|
|
unsigned int get_bg_color() { return m_bg_color; }
|
|
void set_font_type(const FONT_INFO *font_type) { m_font_type = font_type; }
|
|
const FONT_INFO* get_font_type() { return m_font_type; }
|
|
|
|
void set_wnd_pos(short x, short y, short width, short height)
|
|
{
|
|
m_wnd_rect.m_left = x;
|
|
m_wnd_rect.m_top = y;
|
|
m_wnd_rect.m_right = x + width - 1;
|
|
m_wnd_rect.m_bottom = y + height - 1;
|
|
}
|
|
void get_wnd_rect(c_rect &rect) const { rect = m_wnd_rect; }
|
|
void get_screen_rect(c_rect &rect) const
|
|
{
|
|
rect.SetRect(0, 0, (m_wnd_rect.Width() - 1), (m_wnd_rect.Height() - 1));
|
|
wnd2screen(rect);
|
|
}
|
|
|
|
c_wnd* set_child_focus(c_wnd *focus_child)
|
|
{
|
|
ASSERT(0 != focus_child);
|
|
ASSERT(focus_child->m_parent == this);
|
|
|
|
c_wnd* old_focus_child = m_focus_child;
|
|
if (focus_child->is_focus_wnd())
|
|
{
|
|
if (focus_child != old_focus_child)
|
|
{
|
|
if (old_focus_child)
|
|
{
|
|
old_focus_child->on_kill_focus();
|
|
}
|
|
m_focus_child = focus_child;
|
|
m_focus_child->on_focus();
|
|
}
|
|
}
|
|
return m_focus_child;
|
|
}
|
|
|
|
c_wnd* get_parent() const { return m_parent; }
|
|
c_wnd* get_last_child() const
|
|
{
|
|
if (0 == m_top_child)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
c_wnd* child = m_top_child;
|
|
|
|
while (child->m_next_sibling)
|
|
{
|
|
child = child->m_next_sibling;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
int unlink_child(c_wnd *child)
|
|
{
|
|
if ((0 == child)
|
|
|| (this != child->m_parent))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (0 == m_top_child)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
bool find = false;
|
|
|
|
c_wnd* tmp_child = m_top_child;
|
|
if (tmp_child == child)
|
|
{
|
|
m_top_child = child->m_next_sibling;
|
|
if (0 != child->m_next_sibling)
|
|
{
|
|
child->m_next_sibling->m_prev_sibling = 0;
|
|
}
|
|
|
|
find = true;
|
|
}
|
|
else
|
|
{
|
|
while (tmp_child->m_next_sibling)
|
|
{
|
|
if (child == tmp_child->m_next_sibling)
|
|
{
|
|
tmp_child->m_next_sibling = child->m_next_sibling;
|
|
if (0 != child->m_next_sibling)
|
|
{
|
|
child->m_next_sibling->m_prev_sibling = tmp_child;
|
|
}
|
|
|
|
find = true;
|
|
break;
|
|
}
|
|
|
|
tmp_child = tmp_child->m_next_sibling;
|
|
}
|
|
}
|
|
|
|
if (true == find)
|
|
{
|
|
if (m_focus_child == child)
|
|
{
|
|
m_focus_child = 0;
|
|
}
|
|
|
|
child->m_next_sibling = 0;
|
|
child->m_prev_sibling = 0;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
c_wnd* get_prev_sibling() const { return m_prev_sibling; }
|
|
c_wnd* get_next_sibling() const { return m_next_sibling; }
|
|
|
|
void notify_parent(int msg_id, int param)
|
|
{
|
|
if (!m_parent)
|
|
{
|
|
return;
|
|
}
|
|
const GL_MSG_ENTRY* entry = m_parent->find_msg_entry(m_parent->get_msg_entries(), MSG_TYPE_WND, msg_id);
|
|
if (0 == entry)
|
|
{
|
|
return;
|
|
}
|
|
(m_parent->*(entry->callBack))(m_id, param);
|
|
}
|
|
|
|
virtual void on_touch(int x, int y, TOUCH_ACTION action)
|
|
{
|
|
x -= m_wnd_rect.m_left;
|
|
y -= m_wnd_rect.m_top;
|
|
|
|
c_wnd* priority_wnd = 0;
|
|
c_wnd* tmp_child = m_top_child;
|
|
while (tmp_child)
|
|
{
|
|
if ((tmp_child->m_attr & ATTR_PRIORITY) && (tmp_child->m_attr & ATTR_VISIBLE))
|
|
{
|
|
priority_wnd = tmp_child;
|
|
break;
|
|
}
|
|
tmp_child = tmp_child->m_next_sibling;
|
|
}
|
|
if (priority_wnd)
|
|
{
|
|
return priority_wnd->on_touch(x, y, action);
|
|
}
|
|
|
|
c_wnd* child = m_top_child;
|
|
while (child)
|
|
{
|
|
if (child->is_focus_wnd())
|
|
{
|
|
c_rect rect;
|
|
child->get_wnd_rect(rect);
|
|
if (true == rect.PtInRect(x, y))
|
|
{
|
|
return child->on_touch(x, y, action);
|
|
}
|
|
}
|
|
child = child->m_next_sibling;
|
|
}
|
|
}
|
|
virtual void on_key(KEY_TYPE key)
|
|
{
|
|
c_wnd* priority_wnd = 0;
|
|
c_wnd* tmp_child = m_top_child;
|
|
while (tmp_child)
|
|
{
|
|
if ((tmp_child->m_attr & ATTR_PRIORITY) && (tmp_child->m_attr & ATTR_VISIBLE))
|
|
{
|
|
priority_wnd = tmp_child;
|
|
break;
|
|
}
|
|
tmp_child = tmp_child->m_next_sibling;
|
|
}
|
|
if (priority_wnd)
|
|
{
|
|
return priority_wnd->on_key(key);
|
|
}
|
|
|
|
if (!is_focus_wnd())
|
|
{
|
|
return;
|
|
}
|
|
if (key != KEY_BACKWARD && key != KEY_FORWARD)
|
|
{
|
|
if (m_focus_child)
|
|
{
|
|
m_focus_child->on_key(key);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Move focus
|
|
c_wnd* old_focus_wnd = m_focus_child;
|
|
// No current focus wnd, new one.
|
|
if (!old_focus_wnd)
|
|
{
|
|
c_wnd* child = m_top_child;
|
|
c_wnd* new_focus_wnd = 0;
|
|
while (child)
|
|
{
|
|
if (child->is_focus_wnd())
|
|
{
|
|
new_focus_wnd = child;
|
|
new_focus_wnd->m_parent->set_child_focus(new_focus_wnd);
|
|
child = child->m_top_child;
|
|
continue;
|
|
}
|
|
child = child->m_next_sibling;
|
|
}
|
|
return;
|
|
}
|
|
// Move focus from old wnd to next wnd
|
|
c_wnd* next_focus_wnd = (key == KEY_FORWARD) ? old_focus_wnd->m_next_sibling : old_focus_wnd->m_prev_sibling;
|
|
while (next_focus_wnd && (!next_focus_wnd->is_focus_wnd()))
|
|
{// Search neighbor of old focus wnd
|
|
next_focus_wnd = (key == KEY_FORWARD) ? next_focus_wnd->m_next_sibling : next_focus_wnd->m_prev_sibling;
|
|
}
|
|
if (!next_focus_wnd)
|
|
{// Search whole brother wnd
|
|
next_focus_wnd = (key == KEY_FORWARD) ? old_focus_wnd->m_parent->m_top_child : old_focus_wnd->m_parent->get_last_child();
|
|
while (next_focus_wnd && (!next_focus_wnd->is_focus_wnd()))
|
|
{
|
|
next_focus_wnd = (key == KEY_FORWARD) ? next_focus_wnd->m_next_sibling : next_focus_wnd->m_prev_sibling;
|
|
}
|
|
}
|
|
if (next_focus_wnd)
|
|
{
|
|
next_focus_wnd->m_parent->set_child_focus(next_focus_wnd);
|
|
}
|
|
}
|
|
|
|
c_surface* get_surface() { return m_surface; }
|
|
void set_surface(c_surface* surface) { m_surface = surface; }
|
|
protected:
|
|
virtual void pre_create_wnd() {};
|
|
void add_child_2_tail(c_wnd *child)
|
|
{
|
|
if (0 == child)return;
|
|
if (child == get_wnd_ptr(child->m_id))return;
|
|
|
|
if (0 == m_top_child)
|
|
{
|
|
m_top_child = child;
|
|
child->m_prev_sibling = 0;
|
|
child->m_next_sibling = 0;
|
|
}
|
|
else
|
|
{
|
|
c_wnd* last_child = get_last_child();
|
|
if (0 == last_child)
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
last_child->m_next_sibling = child;
|
|
child->m_prev_sibling = last_child;
|
|
child->m_next_sibling = 0;
|
|
}
|
|
}
|
|
|
|
void wnd2screen(int &x, int &y) const
|
|
{
|
|
c_wnd* parent = m_parent;
|
|
c_rect rect;
|
|
|
|
x += m_wnd_rect.m_left;
|
|
y += m_wnd_rect.m_top;
|
|
|
|
while (0 != parent)
|
|
{
|
|
parent->get_wnd_rect(rect);
|
|
x += rect.m_left;
|
|
y += rect.m_top;
|
|
|
|
parent = parent->m_parent;
|
|
}
|
|
}
|
|
|
|
void wnd2screen(c_rect &rect) const
|
|
{
|
|
int l = rect.m_left;
|
|
int t = rect.m_top;
|
|
wnd2screen(l, t);
|
|
|
|
int r = (l + rect.Width() - 1);
|
|
int b = (t + rect.Height() - 1);
|
|
rect.SetRect(l, t, r, b);
|
|
}
|
|
|
|
int load_child_wnd(WND_TREE *p_child_tree)
|
|
{
|
|
if (0 == p_child_tree)
|
|
{
|
|
return 0;
|
|
}
|
|
int sum = 0;
|
|
|
|
WND_TREE* p_cur = p_child_tree;
|
|
while (p_cur->p_wnd)
|
|
{
|
|
if (0 != p_cur->p_wnd->m_id)
|
|
{//This wnd has been used! Do not share!
|
|
ASSERT(false);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
p_cur->p_wnd->connect(this, p_cur->resource_id, p_cur->str,
|
|
p_cur->x, p_cur->y, p_cur->width, p_cur->height, p_cur->p_child_tree);
|
|
}
|
|
p_cur++;
|
|
sum++;
|
|
}
|
|
return sum;
|
|
}
|
|
void set_active_child(c_wnd* child) { m_focus_child = child; }
|
|
|
|
virtual void on_focus() {};
|
|
virtual void on_kill_focus() {};
|
|
protected:
|
|
WND_STATUS m_status;
|
|
WND_ATTRIBUTION m_attr;
|
|
c_rect m_wnd_rect;// position relative to parent wnd.
|
|
c_wnd* m_parent;
|
|
c_wnd* m_top_child;
|
|
c_wnd* m_prev_sibling;
|
|
c_wnd* m_next_sibling;
|
|
const char* m_str;
|
|
|
|
const FONT_INFO* m_font_type;
|
|
unsigned int m_font_color;
|
|
unsigned int m_bg_color;
|
|
|
|
unsigned short m_id;
|
|
|
|
int m_z_order;
|
|
c_wnd* m_focus_child;//current focused wnd
|
|
c_surface* m_surface;
|
|
private:
|
|
c_wnd(const c_wnd &win);
|
|
c_wnd& operator=(const c_wnd &win);
|
|
};
|
|
#endif
|