netsurf/atari/toolbar.c

583 lines
14 KiB
C

/*
* Copyright 2012 Ole Loots <ole@monochrom.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf 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; version 2 of the License.
*
* NetSurf 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, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include "utils/log.h"
#include "desktop/gui.h"
#include "desktop/history_core.h"
#include "desktop/netsurf.h"
#include "desktop/browser.h"
#include "desktop/browser_private.h"
#include "desktop/mouse.h"
#include "desktop/plot_style.h"
#include "desktop/plotters.h"
#include "desktop/tree.h"
#include "desktop/options.h"
#include "utils/utf8.h"
#include "atari/clipboard.h"
#include "atari/gui.h"
#include "atari/toolbar.h"
#include "atari/rootwin.h"
#include "atari/browser.h"
#include "atari/clipboard.h"
#include "atari/misc.h"
#include "atari/global_evnt.h"
#include "atari/plot/plot.h"
#include "cflib.h"
#include "atari/res/netsurf.rsh"
#include "desktop/textarea.h"
#include "desktop/textinput.h"
#include "content/hlcache.h"
#include "atari/browser.h"
#define TB_BUTTON_WIDTH 32
#define THROBBER_WIDTH 32
#define THROBBER_MIN_INDEX 1
#define THROBBER_MAX_INDEX 12
#define THROBBER_INACTIVE_INDEX 13
#define TOOLBAR_URL_MARGIN_LEFT 2
#define TOOLBAR_URL_MARGIN_RIGHT 2
#define TOOLBAR_URL_MARGIN_TOP 2
#define TOOLBAR_URL_MARGIN_BOTTOM 2
enum e_toolbar_button_states {
button_on = 0,
button_off = 1
};
#define TOOLBAR_BUTTON_NUM_STATES 2
struct s_toolbar;
struct s_tb_button
{
short rsc_id;
void (*cb_click)(struct s_toolbar *tb);
hlcache_handle *icon[TOOLBAR_BUTTON_NUM_STATES];
struct s_toolbar *owner;
short state;
short index;
GRECT area;
};
extern char * option_homepage_url;
extern void * h_gem_rsrc;
extern struct gui_window * input_window;
extern long atari_plot_flags;
extern int atari_plot_vdi_handle;
static OBJECT * aes_toolbar = NULL;
static OBJECT * throbber_form = NULL;
static bool img_toolbar = false;
static char * toolbar_image_folder = (char *)"default";
static uint32_t toolbar_bg_color = 0xFFFFFF;
static hlcache_handle * toolbar_image;
static hlcache_handle * throbber_image;
static bool toolbar_image_ready = false;
static bool throbber_image_ready = false;
static bool init = false;
static plot_font_style_t font_style_url = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
.size = 14*FONT_SIZE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0xffffff,
.foreground = 0x0
};
/* prototypes & order for button widgets: */
static struct s_tb_button tb_buttons[] =
{
{
TOOLBAR_BT_BACK,
toolbar_back_click,
{0,0},
0, 0, 0, {0,0,0,0}
},
{
TOOLBAR_BT_HOME,
toolbar_home_click,
{0,0},
0, 0, 0, {0,0,0,0}
},
{
TOOLBAR_BT_FORWARD,
toolbar_forward_click,
{0,0},
0, 0, 0, {0,0,0,0}
},
{
TOOLBAR_BT_STOP,
toolbar_stop_click,
{0,0},
0, 0, 0, {0,0,0,0}
},
{
TOOLBAR_BT_RELOAD,
toolbar_reload_click,
{0,0},
0, 0, 0, {0,0,0,0}
},
{ 0, 0, {0,0}, 0, -1, 0, {0,0,0,0}}
};
struct s_toolbar_style {
int font_height_pt;
int height;
int icon_width;
int icon_height;
int button_hmargin;
int button_vmargin;
/* RRGGBBAA: */
uint32_t icon_bgcolor;
};
static struct s_toolbar_style toolbar_styles[] =
{
/* small (18 px height) */
{ 9, 18, 16, 16, 0, 0, 0 },
/* medium (default - 26 px height) */
{14, 26, 24, 24, 1, 4, 0 },
/* large ( 49 px height ) */
{18, 34, 64, 64, 2, 0, 0 },
/* custom style: */
{18, 34, 64, 64, 2, 0, 0 }
};
static const struct redraw_context toolbar_rdrw_ctx = {
.interactive = true,
.background_images = true,
.plot = &atari_plotters
};
static void tb_txt_request_redraw(void *data, int x, int y, int w, int h );
static nserror toolbar_icon_callback( hlcache_handle *handle,
const hlcache_event *event, void *pw );
/**
* Callback for textarea redraw
*/
static void tb_txt_request_redraw(void *data, int x, int y, int w, int h)
{
GRECT area;
struct s_toolbar * tb = (struct s_toolbar *)data;
toolbar_get_grect(tb, TOOLBAR_URL_AREA, &area);
area.g_x += x;
area.g_y += y;
area.g_w = w;
area.g_h = h;
dbg_grect("toolbar redraw request", &area);
window_schedule_redraw_grect(tb->owner, &area);
return;
}
/**
* Callback for load_icon(). Should be removed once bitmaps get loaded directly
* from disc
*/
static nserror toolbar_icon_callback(hlcache_handle *handle,
const hlcache_event *event, void *pw)
{
if( event->type == CONTENT_MSG_READY ){
if( handle == toolbar_image ){
toolbar_image_ready = true;
if(input_window != NULL )
toolbar_update_buttons(input_window->root->toolbar,
input_window->browser->bw, 0);
}
else if(handle == throbber_image ){
throbber_image_ready = true;
}
}
return NSERROR_OK;
}
static struct s_tb_button *button_init(struct s_toolbar *tb, OBJECT * tree, int index,
struct s_tb_button * instance)
{
*instance = tb_buttons[index];
instance->owner = tb;
instance->area.g_w = toolbar_styles[tb->style].icon_width + \
( toolbar_styles[tb->style].button_vmargin * 2);
return(instance);
}
void toolbar_init( void )
{
int i=0, n;
short vdicolor[3];
uint32_t rgbcolor;
toolbar_image_folder = nsoption_charp(atari_image_toolbar_folder);
toolbar_bg_color = (nsoption_colour(atari_toolbar_bg));
img_toolbar = (nsoption_int(atari_image_toolbar) > 0 ) ? true : false;
if( img_toolbar ){
char imgfile[PATH_MAX];
const char * imgfiletmpl = "toolbar/%s/%s";
while( tb_buttons[i].rsc_id != 0){
tb_buttons[i].index = i;
i++;
}
snprintf( imgfile, PATH_MAX-1, imgfiletmpl, toolbar_image_folder,
"main.png" );
toolbar_image = load_icon( imgfile,
toolbar_icon_callback, NULL );
snprintf( imgfile, PATH_MAX-1, imgfiletmpl, toolbar_image_folder,
"throbber.png" );
throbber_image = load_icon( imgfile,
toolbar_icon_callback, NULL );
} else {
aes_toolbar = get_tree(TOOLBAR);
throbber_form = get_tree(THROBBER);
}
n = (sizeof( toolbar_styles ) / sizeof( struct s_toolbar_style ));
for (i=0; i<n; i++) {
toolbar_styles[i].icon_bgcolor = ABGR_TO_RGB(toolbar_bg_color);
}
}
void toolbar_exit(void)
{
if (toolbar_image)
hlcache_handle_release(toolbar_image);
if (throbber_image)
hlcache_handle_release(throbber_image);
}
struct s_toolbar *toolbar_create(struct s_gui_win_root *owner)
{
int i;
LOG((""));
struct s_toolbar *t = calloc(sizeof(struct s_toolbar), 1);
assert(t);
t->owner = owner;
t->style = 1;
/* create the root component: */
t->area.g_h = toolbar_styles[t->style].height;
/* count buttons and add them as components: */
i = 0;
while(tb_buttons[i].rsc_id > 0) {
i++;
}
t->btcnt = i;
t->buttons = malloc(t->btcnt * sizeof(struct s_tb_button));
memset( t->buttons, 0, t->btcnt * sizeof(struct s_tb_button));
for (i=0; i < t->btcnt; i++ ) {
button_init(t, aes_toolbar, i, &t->buttons[i]);
}
/* create the url widget: */
font_style_url.size =
toolbar_styles[t->style].font_height_pt * FONT_SIZE_SCALE;
int ta_height = toolbar_styles[t->style].height;
ta_height -= (TOOLBAR_URL_MARGIN_TOP + TOOLBAR_URL_MARGIN_BOTTOM);
t->url.textarea = textarea_create(300, ta_height, 0, &font_style_url,
tb_txt_request_redraw, t);
/* create the throbber widget: */
t->throbber.area.g_h = toolbar_styles[t->style].height;
t->throbber.area.g_w = toolbar_styles[t->style].icon_width + \
(2*toolbar_styles[t->style].button_vmargin );
if( img_toolbar == true ){
t->throbber.index = 0;
t->throbber.max_index = 8;
} else {
t->throbber.running = false;
t->throbber.index = THROBBER_INACTIVE_INDEX;
t->throbber.max_index = THROBBER_MAX_INDEX;
}
t->throbber.running = false;
LOG(("created toolbar: %p, root: %p, textarea: %p, throbber: %p", t,
owner, t->url.textarea, t->throbber));
return( t );
}
void toolbar_destroy(struct s_toolbar *tb)
{
free(tb->buttons);
textarea_destroy( tb->url.textarea );
free(tb);
}
static void toolbar_reflow(struct s_toolbar *tb)
{
// position toolbar areas:
aes_toolbar->ob_x = tb->area.g_x;
aes_toolbar->ob_y = tb->area.g_y;
aes_toolbar->ob_width = tb->area.g_w;
aes_toolbar->ob_height = tb->area.g_h;
aes_toolbar[TOOLBAR_THROBBER_AREA].ob_x = tb->area.g_w
- aes_toolbar[TOOLBAR_THROBBER_AREA].ob_width;
aes_toolbar[TOOLBAR_URL_AREA].ob_width = tb->area.g_w
- (aes_toolbar[TOOLBAR_NAVIGATION_AREA].ob_width
+ aes_toolbar[TOOLBAR_THROBBER_AREA].ob_width + 1);
// position throbber image:
throbber_form[tb->throbber.index].ob_x = tb->area.g_x +
aes_toolbar[TOOLBAR_THROBBER_AREA].ob_x;
throbber_form[tb->throbber.index].ob_x = tb->area.g_x
+ aes_toolbar[TOOLBAR_THROBBER_AREA].ob_x +
((aes_toolbar[TOOLBAR_THROBBER_AREA].ob_width
- throbber_form[tb->throbber.index].ob_width) >> 1);
throbber_form[tb->throbber.index].ob_y = tb->area.g_y +
((aes_toolbar[TOOLBAR_THROBBER_AREA].ob_height
- throbber_form[tb->throbber.index].ob_height) >> 1);
tb->reflow = false;
}
void toolbar_redraw(struct s_toolbar *tb, GRECT *clip)
{
GRECT area;
if(tb->reflow == true)
toolbar_reflow(tb);
objc_draw_grect(aes_toolbar,0,8,clip);
objc_draw_grect(&throbber_form[tb->throbber.index], 0, 1, clip);
GRECT url_area;
toolbar_get_grect(tb, TOOLBAR_URL_AREA, &area);
url_area = area;
if (rc_intersect(clip, &area)) {
struct rect r = {
.x0 = 0,
.y0 = 0,
.x1 = url_area.g_w,
.y1 = url_area.g_h
};
r.x0 = area.g_x - url_area.g_x;
r.x1 = r.x0 + area.g_w;
plot_set_dimensions(url_area.g_x, url_area.g_y, url_area.g_w,
url_area.g_h);
textarea_set_dimensions(tb->url.textarea,
aes_toolbar[TOOLBAR_URL_AREA].ob_width,
20);
textarea_redraw(tb->url.textarea, 0, 0, &r, &toolbar_rdrw_ctx);
}
}
void toolbar_update_buttons(struct s_toolbar *tb, struct browser_window *bw,
short button)
{
LOG((""));
}
void toolbar_set_dimensions(struct s_toolbar *tb, GRECT *area)
{
tb->area = *area;
tb->reflow = true;
}
void toolbar_set_url(struct s_toolbar *tb, const char * text)
{
LOG((""));
textarea_set_text(tb->url.textarea, text);
GRECT area;
toolbar_get_grect(tb, TOOLBAR_URL_AREA, &area);
window_schedule_redraw_grect(tb->owner, &area);
}
void toolbar_set_throbber_state(struct s_toolbar *tb, bool active)
{
GRECT throbber_area;
tb->throbber.running = active;
if (active) {
tb->throbber.index = THROBBER_MIN_INDEX;
} else {
tb->throbber.index = THROBBER_INACTIVE_INDEX;
}
tb->reflow = true;
toolbar_get_grect(tb, TOOLBAR_THROBBER_AREA, &throbber_area);
window_schedule_redraw_grect(tb->owner, &throbber_area);
}
void toolbar_throbber_progress(struct s_toolbar *tb)
{
GRECT throbber_area;
assert(tb->throbber.running == true);
if(tb->throbber.running == false)
return;
tb->throbber.index++;
if(tb->throbber.index > THROBBER_MAX_INDEX)
tb->throbber.index = THROBBER_MIN_INDEX;
tb->reflow = true;
toolbar_get_grect(tb, TOOLBAR_THROBBER_AREA, &throbber_area);
window_schedule_redraw_grect(tb->owner, &throbber_area);
}
bool toolbar_text_input(struct s_toolbar *tb, char *text)
{
bool handled = true;
LOG((""));
return(handled);
}
bool toolbar_key_input(struct s_toolbar *tb, short nkc)
{
bool handled = true;
LOG((""));
return(handled);
}
void toolbar_mouse_input(struct s_toolbar *tb, short mx, short my)
{
LOG((""));
}
/**
* Receive a specific region of the toolbar.
* @param tb - the toolbar pointer
* @param which - the area to retrieve: TOOLBAR_URL_AREA,
* TOOLBAR_NAVIGATION_AREA,
* TOOLBAR_THROBBER_AREA
* @param dst - GRECT pointer receiving the area.
*/
void toolbar_get_grect(struct s_toolbar *tb, short which, GRECT *dst)
{
if (tb->reflow == true) {
toolbar_reflow(tb);
}
objc_offset(aes_toolbar, which, &dst->g_x, &dst->g_y);
dst->g_w = aes_toolbar[which].ob_width;
dst->g_h = aes_toolbar[which].ob_height;
//printf("Toolbar get grect (%d): ", which);
//dbg_grect("", dst);
}
struct text_area *toolbar_get_textarea(struct s_toolbar *tb,
enum toolbar_textarea which)
{
return(tb->url.textarea);
}
/* public event handler */
void toolbar_back_click(struct s_toolbar *tb)
{
assert(input_window != NULL);
struct browser_window *bw = input_window->browser->bw;
if( history_back_available(bw->history) )
history_back(bw, bw->history);
}
void toolbar_reload_click(struct s_toolbar *tb)
{
assert(input_window != NULL);
browser_window_reload(input_window->browser->bw, true);
}
void toolbar_forward_click(struct s_toolbar *tb)
{
assert(input_window != NULL);
struct browser_window *bw = input_window->browser->bw;
if (history_forward_available(bw->history))
history_forward(bw, bw->history);
}
void toolbar_home_click(struct s_toolbar *tb)
{
assert(input_window != NULL);
struct browser_window * bw;
struct gui_window * gw;
gw = window_get_active_gui_window(tb->owner);
bw = gw->browser->bw;
browser_window_go(bw, option_homepage_url, 0, true);
}
void toolbar_stop_click(struct s_toolbar *tb)
{
assert(input_window != NULL);
browser_window_stop(input_window->browser->bw);
}