gambas-source-code/gb.gtk/src/gcontrol.h
gambas 86caf66c56 Fix focus management and container arrangement.
[GB.GTK]
* BUG: Fix focus management and container arrangement.

[GB.GTK3]
* BUG: Fix focus management and container arrangement.
2022-02-23 19:29:21 +01:00

396 lines
12 KiB
C++

/***************************************************************************
gcontrol.h
(c) 2000-2017 Benoît Minisini <g4mba5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#ifndef __GCONTROL_H
#define __GCONTROL_H
#include "gcolor.h"
#include "gdrag.h"
class gContainer;
class gMainWindow;
#ifdef GTK3
void gt_patch_control(GtkWidget *widget);
#endif
class gControl
{
public:
gControl();
gControl(gContainer *parent);
virtual ~gControl();
void *hFree;
bool isContainer() const { return _is_container; }
bool isWindow() const { return _is_window; }
bool isButton() const { return _is_button; }
bool isDrawingArea() const { return _is_drawingarea; }
bool isTopLevel() const { return pr == NULL; }
bool isDestroyed() const { return _destroyed; }
gMainWindow *window() const;
gMainWindow *topLevel() const;
gContainer *parent() const { return pr; }
bool isAncestorOf(gControl *child);
bool isDesign() const { return _design && !_no_design; }
bool isDesignIgnore() const { return _design_ignore; }
bool hovered();
virtual long handle();
int left() const { return bufX; }
int x() const { return left(); }
int top() const { return bufY; }
int y() const { return top(); }
int width() const { return bufW; }
int height() const { return bufH; }
void setLeft(int v) { move(v, y()); }
void setTop(int v) { move(x(), v); }
void setWidth(int w) { resize(w, height()); }
void setHeight(int h) { resize(width(), h); }
virtual void move(int x, int y);
virtual bool resize(int w, int h, bool no_decide = false);
void resize() { resize(width(), height()); }
void moveResize(int x, int y, int w, int h, bool no_decide = false);
void getGeometry(GdkRectangle *rect) const { rect->x = bufX; rect->y = bufY; rect->width = bufW; rect->height = bufH; }
void setGeometry(GdkRectangle *rect) { moveResize(rect->x, rect->y, rect->width, rect->height); }
bool isVisible() const { return _visible; }
bool isReallyVisible();
virtual void setVisible(bool v);
void hide() { setVisible(false); }
void show() { setVisible(true); }
void setVisibility(bool v);
void checkVisibility();
virtual bool isEnabled() const;
virtual void setEnabled(bool vl);
int mouse();
void setMouse(int m);
gCursor* cursor();
void setCursor(gCursor *vl);
virtual void updateCursor(GdkCursor *cursor);
gControl *next();
gControl *previous();
gControl *nextFocus();
gControl *previousFocus();
void setPrevious(gControl *prev);
void setNext(gControl *next);
int screenX();
int screenY();
virtual bool getScreenPos(int *x, int *y);
bool isExpand() const { return _expand; }
bool isIgnore() const { return _ignore; }
void setExpand (bool vl);
void setIgnore (bool vl);
bool acceptDrops() const { return _accept_drops; }
void setAcceptDrops(bool vl);
const char *name() const { return _name; }
void setName(char *name);
bool action() const { return _action; }
void setAction(bool v) { _action = v; }
virtual void setDesign(bool ignore = false);
gControl *ignoreDesign();
void updateDesign();
char *tooltip() { return _tooltip; }
void setTooltip(char *vl);
bool isTracking() const;
void setTracking(bool vl);
bool isNoTabFocus() const;
bool isNoTabFocusRec() const;
void setNoTabFocus(bool v);
void setDirection(int v);
int direction() const { return _direction; }
void setInverted(bool v);
bool isInverted() const { return _inverted; }
bool isRightToLeft() const;
gColor background() const { return _bg; }
gColor foreground() const { return _fg; }
virtual void setBackground(gColor color = COLOR_DEFAULT);
virtual void setForeground(gColor color = COLOR_DEFAULT);
virtual gColor defaultBackground() const;
gColor realBackground(bool no_default = false);
gColor realForeground(bool no_default = false);
virtual void setRealBackground(gColor color);
virtual void setRealForeground(gColor color);
virtual gFont *font() const;
void actualFontTo(gFont *ft);
virtual void setFont(gFont *ft);
bool ownFont() { return _font != NULL; }
virtual void updateFont();
virtual void updateSize();
bool hasNativePopup() const { return _has_native_popup; }
#ifdef GTK3
void setWidgetName();
virtual GtkWidget *getStyleSheetWidget();
virtual const char *getStyleSheetColorNode();
virtual const char *getStyleSheetFontNode();
void updateStyleSheet(bool dirty);
virtual void customStyleSheet(GString *css);
void setStyleSheetNode(GString *css, const char *node);
virtual void updateColor();
#else
void setColorNames(const char **, const char **) {}
#endif
void setColorBase() { use_base = TRUE; }
void setColorButton() { use_base = FALSE; }
virtual bool canFocus() const;
bool canFocusOnClick() const;
void setCanFocus(bool vl);
bool eatReturnKey() const { return _eat_return_key; }
gControl *proxy() const { return _proxy; }
bool setProxy(gControl *proxy);
int scrollX();
int scrollY();
void scroll(int x, int y);
void setScrollX(int vl);
void setScrollY(int vl);
int scrollBar() const { return _scrollbar; }
void setScrollBar(int vl);
virtual void updateScrollBar();
bool isDragging() const { return _dragging; }
void dragText(char *txt, char *format = NULL) { gDrag::dragText(this, txt, format); }
void dragImage(gPicture *pic) { gDrag::dragImage(this, pic); }
virtual void reparent(gContainer *newpr, int x, int y);
void lower() { restack(false); }
void raise() { restack(true); }
virtual void restack(bool raise);
virtual void setFocus();
bool hasFocus() const;
#if GTK_CHECK_VERSION(3, 2, 0)
bool hasVisibleFocus() const;
#else
bool hasVisibleFocus() const { return hasFocus(); }
#endif
void refresh();
void refresh(int x, int y, int w, int h);
virtual void afterRefresh();
bool grab();
virtual void destroy();
void destroyNow() { destroy(); postDelete(); }
void lock() { _locked++; }
void unlock() { _locked--; }
bool locked() const { return _locked; }
void emit(void *signal);
void emit(void *signal, intptr_t arg);
void emit(void *signal, char *arg) { emit(signal, (intptr_t)arg); }
// "Private"
gint bufW,bufH,bufX,bufY;
int _min_w, _min_h;
gCursor *curs;
gFont *_font;
gFont *_resolved_font;
GtkWidget *widget;
GtkWidget *border;
GtkWidget *frame;
GtkScrolledWindow *_scroll;
short _mouse;
gControl *_proxy, *_proxy_for;
gColor _bg, _fg;
char *_tooltip;
#ifdef GTK3
GtkStyleProvider *_css;
const char *_css_node;
#endif
unsigned _destroyed : 1; // If the control has already been added to the destroy list
unsigned _design : 1;
unsigned _design_ignore : 1;
unsigned _no_design : 1;
unsigned _expand : 1;
unsigned _ignore : 1;
unsigned _action : 1; // *reserved*
unsigned _inverted : 1; // if the widget direction has been inverted
unsigned _accept_drops : 1; // If the control accepts drops
unsigned _dragging : 1; // if the control is being dragged
unsigned _drag_get_data : 1; // If we got information on the dragged data
unsigned _tracking : 1; // If we are tracking mouse move even if no mouse button is pressed
unsigned _old_tracking : 1; // real value when Tracking is false
unsigned _bg_set : 1; // Have a private background
unsigned _fg_set : 1; // Have a private foreground
unsigned have_cursor : 1; // If gApplication::setBusy() must update the cursor
unsigned use_base : 1; // Use base and text color for foreground and background
unsigned _visible : 1; // A control can be hidden if its width or height is zero
unsigned _no_delete : 1; // Do not delete on destroy signal
unsigned _scrollbar : 2;
unsigned _dirty_pos : 1; // If the position of the widget has changed
unsigned _dirty_size : 1; // If the size of the widget has changed
unsigned _inside : 1; // if we got an enter event, but not a leave event yet.
unsigned _locked : 4; // For locking events
unsigned frame_border : 4;
unsigned frame_padding : 8;
unsigned _has_input_method : 1; // Has its own input method management
unsigned _no_default_mouse_event : 1; // No default mouse events
unsigned _grab : 1; // control is currently grabbing mouse and keyboard
unsigned _has_border : 1; // if the control has a border
unsigned _no_tab_focus : 1; // Don't put inside focus chain
unsigned _no_auto_grab : 1; // do not automatically grab widget on button press event
unsigned _no_background : 1; // Don't draw the background automatically
unsigned _use_wheel : 1; // Do not propagate the mouse wheel event
unsigned _is_container : 1; // I am a container
unsigned _is_window : 1; // I am a window
unsigned _is_button : 1; // I am a button
unsigned _is_drawingarea : 1; // I am a drawing area
unsigned _has_native_popup : 1; // I have a native popup menu
unsigned _eat_return_key : 1; // If the control eats the return key
unsigned _minimum_size_set : 1; // If minimum size has been computed
unsigned _allow_show : 1; // Allowed to be visible (after the first resize)
unsigned _direction : 2; // Text direction
#ifdef GTK3
unsigned _style_dirty : 1; // If the style must be refreshed
unsigned _no_style_without_child : 1; // For containers that do not need a css if they have no children
unsigned _has_css_id : 1; // If the widget has a css id
#endif
void removeParent() { pr = NULL; }
void initSignals();
virtual void borderSignals();
void widgetSignals();
void connectParent();
void setParent(gContainer *parent) { pr = parent; }
void initAll(gContainer *pr);
void realize(bool draw_frame = false);
void realizeScrolledWindow(GtkWidget *wid, bool doNotRealize = false);
void registerControl();
void updateGeometry(bool force = false);
bool mustUpdateCursor() { return mouse() != -1 || have_cursor || !parent(); }
void updateEventMask();
bool hasInputMethod() { return _has_input_method; }
virtual GtkIMContext *getInputMethod();
GdkCursor *getGdkCursor();
virtual void updateBorder();
int getFrameBorder() const { return frame_border; }
void setFrameBorder(int border);
virtual void setBorder(bool b);
bool hasBorder() const;
int getFramePadding() const { return frame_padding; }
void setFramePadding(int padding);
virtual int getFrameWidth() const;
virtual gColor getFrameColor();
#ifdef GTK3
void drawBorder(cairo_t *cr);
void drawBackground(cairo_t *cr);
#else
void drawBorder(GdkEventExpose *e);
void drawBackground(GdkEventExpose *e);
#endif
void createBorder(GtkWidget *new_border, bool keep_widget = false);
void createWidget();
int minimumWidth() const { return _min_w; }
int minimumHeight() const { return _min_h; }
virtual void setMinimumSize();
void resolveFont();
void emitEnterEvent(bool no_leave = false);
void emitLeaveEvent();
#ifdef GTK3
virtual void onEnterEvent();
virtual void onLeaveEvent();
#endif
void hideButKeepFocus();
void showButKeepFocus();
int actualDirection() const;
virtual void updateDirection();
static void postDelete();
private:
gContainer *pr;
char *_name;
GtkIMContext *_input_method;
void dispose();
};
#define SIGNAL(_signal) ((void *)_signal)
// Callbacks
// "Signals"
bool CB_control_can_raise(gControl *sender, int type);
void CB_control_finish(gControl *sender);
void CB_control_focus(gControl *sender, int type);
bool CB_control_key(gControl *sender, int type);
bool CB_control_mouse(gControl *sender, int type);
void CB_control_enter_leave(gControl *sender, int type);
bool CB_control_drag(gControl *sender);
bool CB_control_drag_move(gControl *sender);
bool CB_control_drop(gControl *sender);
void CB_control_drag_leave(gControl *sender);
#endif