and a lot more added to photocam + test code

SVN revision: 42693
This commit is contained in:
Carsten Haitzler 2009-09-25 09:26:04 +00:00
parent 5b6f2d5b2d
commit c880a4f5ba
14 changed files with 993 additions and 92 deletions

View File

@ -128,7 +128,16 @@ separator_h.png \
separator_v.png \
toolbar_separator_v.png \
sp_bt_l.png \
sp_bt_r.png
sp_bt_r.png \
busy-1.png \
busy-2.png \
busy-3.png \
busy-4.png \
busy-5.png \
busy-6.png \
busy-7.png \
busy-8.png \
busy-9.png
default.edj: Makefile $(EXTRA_DIST)
$(EDJE_CC) $(EDJE_FLAGS) \

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -5197,7 +5197,7 @@ collections {
fill.smooth: 0;
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
@ -14681,4 +14681,528 @@ collections {
}
}
}
///////////////////////////////////////////////////////////////////////////////
group { name: "elm/photocam/base/default";
script {
public sbvis_v, sbvis_h, sbalways_v, sbalways_h, sbvis_timer;
public timer0(val) {
new v;
v = get_int(sbvis_v);
if (v) {
v = get_int(sbalways_v);
if (!v) {
emit("do-hide-vbar", "");
set_int(sbvis_v, 0);
}
}
v = get_int(sbvis_h);
if (v) {
v = get_int(sbalways_h);
if (!v) {
emit("do-hide-hbar", "");
set_int(sbvis_h, 0);
}
}
set_int(sbvis_timer, 0);
return 0;
}
}
images {
image: "shelf_inset.png" COMP;
image: "bt_sm_base2.png" COMP;
image: "bt_sm_shine.png" COMP;
image: "bt_sm_hilight.png" COMP;
image: "sb_runnerh.png" COMP;
image: "sb_runnerv.png" COMP;
image: "busy-1.png" COMP;
image: "busy-2.png" COMP;
image: "busy-3.png" COMP;
image: "busy-4.png" COMP;
image: "busy-5.png" COMP;
image: "busy-6.png" COMP;
image: "busy-7.png" COMP;
image: "busy-8.png" COMP;
image: "busy-9.png" COMP;
}
parts {
part { name: "bg";
type: RECT;
description { state: "default" 0.0;
rel1.offset: 1 1;
rel2.offset: -2 -2;
color: 255 255 255 0;
}
}
part { name: "clipper";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "bg";
rel2.to: "bg";
}
}
part { name: "elm.swallow.content";
clip_to: "clipper";
type: SWALLOW;
description { state: "default" 0.0;
rel1.offset: 1 1;
rel2.offset: -2 -2;
}
}
part { name: "busy_clip";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
visible: 0;
color: 255 255 255 0;
}
description { state: "active" 0.0;
visible: 1;
color: 255 255 255 255;
}
}
part { name: "busy";
clip_to: "busy_clip";
mouse_events: 0;
description { state: "default" 0.0;
fixed: 1 1;
min: 32 32;
aspect: 1.0 1.0;
align: 1.0 1.0;
aspect_preference: BOTH;
rel1 {
relative: 0.9 0.9;
offset: -9 -9;
}
rel2 {
relative: 0.9 0.9;
offset: -9 -9;
}
image {
normal: "busy-9.png";
tween: "busy-1.png";
tween: "busy-2.png";
tween: "busy-3.png";
tween: "busy-4.png";
tween: "busy-5.png";
tween: "busy-6.png";
tween: "busy-7.png";
tween: "busy-8.png";
}
}
}
part { name: "conf_over";
mouse_events: 0;
description { state: "default" 0.0;
rel1.offset: 0 0;
rel2.offset: -1 -1;
image {
normal: "shelf_inset.png";
border: 7 7 7 7;
middle: 0;
}
fill.smooth : 0;
}
}
part { name: "sb_vbar_clip_master";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
}
description { state: "hidden" 0.0;
visible: 0;
color: 255 255 255 0;
}
}
part { name: "sb_vbar_clip";
clip_to: "sb_vbar_clip_master";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
}
description { state: "hidden" 0.0;
visible: 0;
color: 255 255 255 0;
}
}
part { name: "sb_vbar";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
fixed: 1 1;
visible: 0;
min: 17 17;
align: 1.0 0.0;
rel1 {
relative: 1.0 0.0;
offset: -2 0;
}
rel2 {
relative: 1.0 0.0;
offset: -2 -1;
to_y: "sb_hbar";
}
}
}
part { name: "sb_vbar_runner";
clip_to: "sb_vbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
min: 3 3;
max: 3 99999;
rel1.to: "sb_vbar";
rel2.to: "sb_vbar";
image {
normal: "sb_runnerv.png";
border: 0 0 4 4;
}
fill.smooth: 0;
}
}
part { name: "elm.dragable.vbar";
clip_to: "sb_vbar_clip";
mouse_events: 0;
dragable {
x: 0 0 0;
y: 1 1 0;
confine: "sb_vbar";
}
description { state: "default" 0.0;
fixed: 1 1;
min: 17 17;
rel1 {
relative: 0.5 0.5;
offset: 0 0;
to: "sb_vbar";
}
rel2 {
relative: 0.5 0.5;
offset: 0 0;
to: "sb_vbar";
}
image {
normal: "bt_sm_base2.png";
border: 6 6 6 6;
}
image.middle: SOLID;
}
}
part { name: "sb_vbar_over1";
clip_to: "sb_vbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "elm.dragable.vbar";
rel2.relative: 1.0 0.5;
rel2.to: "elm.dragable.vbar";
image {
normal: "bt_sm_hilight.png";
border: 6 6 6 0;
}
}
}
part { name: "sb_vbar_over2";
clip_to: "sb_vbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "elm.dragable.vbar";
rel2.to: "elm.dragable.vbar";
image {
normal: "bt_sm_shine.png";
border: 6 6 6 0;
}
}
}
part { name: "sb_hbar_clip_master";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
}
description { state: "hidden" 0.0;
visible: 0;
color: 255 255 255 0;
}
}
part { name: "sb_hbar_clip";
clip_to: "sb_hbar_clip_master";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
}
description { state: "hidden" 0.0;
visible: 0;
color: 255 255 255 0;
}
}
part { name: "sb_hbar";
type: RECT;
mouse_events: 0;
description { state: "default" 0.0;
fixed: 1 1;
visible: 0;
min: 17 17;
align: 0.0 1.0;
rel1 {
relative: 0.0 1.0;
offset: 0 -2;
}
rel2 {
relative: 0.0 1.0;
offset: -1 -2;
to_x: "sb_vbar";
}
}
}
part { name: "sb_hbar_runner";
clip_to: "sb_hbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
min: 3 3;
max: 99999 3;
rel1.to: "sb_hbar";
rel2.to: "sb_hbar";
image {
normal: "sb_runnerh.png";
border: 4 4 0 0;
}
fill.smooth: 0;
}
}
part { name: "elm.dragable.hbar";
clip_to: "sb_hbar_clip";
mouse_events: 0;
dragable {
x: 1 1 0;
y: 0 0 0;
confine: "sb_hbar";
}
description { state: "default" 0.0;
fixed: 1 1;
min: 17 17;
rel1 {
relative: 0.5 0.5;
offset: 0 0;
to: "sb_hbar";
}
rel2 {
relative: 0.5 0.5;
offset: 0 0;
to: "sb_hbar";
}
image {
normal: "bt_sm_base2.png";
border: 6 6 6 6;
}
image.middle: SOLID;
}
}
part { name: "sb_hbar_over1";
clip_to: "sb_hbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "elm.dragable.hbar";
rel2.relative: 1.0 0.5;
rel2.to: "elm.dragable.hbar";
image {
normal: "bt_sm_hilight.png";
border: 6 6 6 0;
}
}
}
part { name: "sb_hbar_over2";
clip_to: "sb_hbar_clip";
mouse_events: 0;
description { state: "default" 0.0;
rel1.to: "elm.dragable.hbar";
rel2.to: "elm.dragable.hbar";
image {
normal: "bt_sm_shine.png";
border: 6 6 6 0;
}
}
}
}
programs {
program { name: "load";
signal: "load";
source: "";
script {
set_state(PART:"sb_hbar_clip", "hidden", 0.0);
set_state(PART:"sb_vbar_clip", "hidden", 0.0);
set_int(sbvis_h, 0);
set_int(sbvis_v, 0);
set_int(sbalways_v, 0);
set_int(sbalways_h, 0);
set_int(sbvis_timer, 0);
}
}
program { name: "vbar_show";
signal: "elm,action,show,vbar";
source: "elm";
action: STATE_SET "default" 0.0;
target: "sb_vbar_clip_master";
}
program { name: "vbar_hide";
signal: "elm,action,hide,vbar";
source: "elm";
action: STATE_SET "hidden" 0.0;
target: "sb_vbar_clip_master";
}
program { name: "vbar_show_always";
signal: "elm,action,show_always,vbar";
source: "elm";
script {
new v;
v = get_int(sbvis_v);
v |= get_int(sbalways_v);
if (!v) {
set_int(sbalways_v, 1);
emit("do-show-vbar", "");
set_int(sbvis_v, 1);
}
}
}
program { name: "vbar_show_notalways";
signal: "elm,action,show_notalways,vbar";
source: "elm";
script {
new v;
v = get_int(sbalways_v);
if (v) {
set_int(sbalways_v, 0);
v = get_int(sbvis_v);
if (!v) {
emit("do-hide-vbar", "");
set_int(sbvis_v, 0);
}
}
}
}
program { name: "sb_vbar_show";
signal: "do-show-vbar";
source: "";
action: STATE_SET "default" 0.0;
transition: LINEAR 1.0;
target: "sb_vbar_clip";
}
program { name: "sb_vbar_hide";
signal: "do-hide-vbar";
source: "";
action: STATE_SET "hidden" 0.0;
transition: LINEAR 1.0;
target: "sb_vbar_clip";
}
program { name: "hbar_show";
signal: "elm,action,show,hbar";
source: "elm";
action: STATE_SET "default" 0.0;
target: "sb_hbar_clip_master";
}
program { name: "hbar_hide";
signal: "elm,action,hide,hbar";
source: "elm";
action: STATE_SET "hidden" 0.0;
target: "sb_hbar_clip_master";
}
program { name: "hbar_show_always";
signal: "elm,action,show_always,hbar";
source: "elm";
script {
new v;
v = get_int(sbvis_h);
v |= get_int(sbalways_h);
if (!v) {
set_int(sbalways_h, 1);
emit("do-show-hbar", "");
set_int(sbvis_h, 1);
}
}
}
program { name: "hbar_show_notalways";
signal: "elm,action,show_notalways,hbar";
source: "elm";
script {
new v;
v = get_int(sbalways_h);
if (v) {
set_int(sbalways_h, 0);
v = get_int(sbvis_h);
if (!v) {
emit("do-hide-hbar", "");
set_int(sbvis_h, 0);
}
}
}
}
program { name: "sb_hbar_show";
signal: "do-show-hbar";
source: "";
action: STATE_SET "default" 0.0;
transition: LINEAR 1.0;
target: "sb_hbar_clip";
}
program { name: "sb_hbar_hide";
signal: "do-hide-hbar";
source: "";
action: STATE_SET "hidden" 0.0;
transition: LINEAR 1.0;
target: "sb_hbar_clip";
}
program { name: "scroll";
signal: "elm,action,scroll";
source: "elm";
script {
new v;
v = get_int(sbvis_v);
v |= get_int(sbalways_v);
if (!v) {
emit("do-show-vbar", "");
set_int(sbvis_v, 1);
}
v = get_int(sbvis_h);
v |= get_int(sbalways_h);
if (!v) {
emit("do-show-hbar", "");
set_int(sbvis_h, 1);
}
v = get_int(sbvis_timer);
if (v > 0) cancel_timer(v);
v = timer(2.0, "timer0", 0);
set_int(sbvis_timer, v);
}
}
program { name: "go1";
signal: "elm,state,busy,start";
source: "elm";
action: STATE_SET "active" 0.0;
transition: SINUSOIDAL 1.0;
target: "busy_clip";
}
program { name: "go2";
signal: "elm,state,busy,start";
source: "elm";
action: STATE_SET "default" 0.0;
transition: LINEAR 0.5;
target: "busy";
after: "go2";
}
program { name: "stop1";
signal: "elm,state,busy,stop";
source: "elm";
action: STATE_SET "default" 0.0;
transition: SINUSOIDAL 1.0;
target: "busy_clip";
after: "stop2";
}
program { name: "stop2";
action: ACTION_STOP;
target: "go2";
}
}
}
}

View File

@ -1,6 +1,6 @@
#include <Elementary.h>
#ifndef ELM_LIB_QUICKLAUNCH
void
static void
my_bt_zoom_in(void *data, Evas_Object *obj, void *event_info)
{
int zoom;
@ -11,7 +11,52 @@ my_bt_zoom_in(void *data, Evas_Object *obj, void *event_info)
if (zoom >= 1) elm_photocam_zoom_set(data, zoom);
}
void
static void
sel_done(void *data, Evas_Object *obj, void *event_info)
{
Evas_Object *ph, *iw;
ph = data;
iw = evas_object_data_get(ph, "inwin");
elm_photocam_file_set(ph, elm_fileselector_selected_get(obj));
evas_object_del(iw);
}
static void
my_bt_open(void *data, Evas_Object *obj, void *event_info)
{
Evas_Object *ph, *win;
Evas_Object *iw, *fs;
ph = data;
win = evas_object_data_get(ph, "window");
iw = elm_win_inwin_add(win);
fs = elm_fileselector_add(win);
elm_fileselector_expandable_set(fs, EINA_TRUE);
elm_fileselector_path_set(fs, getenv("HOME"));
evas_object_smart_callback_add(fs, "done", sel_done, ph);
evas_object_data_set(ph, "inwin", iw);
elm_win_inwin_content_set(iw, fs);
evas_object_show(fs);
elm_win_inwin_activate(iw);
}
static void
my_bt_show_reg(void *data, Evas_Object *obj, void *event_info)
{
elm_photocam_image_region_show(data, 30, 50, 500, 300);
}
static void
my_bt_bring_reg(void *data, Evas_Object *obj, void *event_info)
{
elm_photocam_image_region_bring_in(data, 800, 300, 500, 300);
}
static void
my_bt_zoom_out(void *data, Evas_Object *obj, void *event_info)
{
int zoom;
@ -22,19 +67,19 @@ my_bt_zoom_out(void *data, Evas_Object *obj, void *event_info)
if (zoom <= 256) elm_photocam_zoom_set(data, zoom);
}
void
static void
my_bt_zoom_man(void *data, Evas_Object *obj, void *event_info)
{
elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
}
void
static void
my_bt_zoom_fit(void *data, Evas_Object *obj, void *event_info)
{
elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT);
}
void
static void
my_bt_zoom_fill(void *data, Evas_Object *obj, void *event_info)
{
elm_photocam_zoom_mode_set(data, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL);
@ -45,7 +90,7 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
{
Evas_Object *win, *bg, *ph, *tb2, *bt;
char buf[PATH_MAX];
// FIXME: add a file selector and a "select a file" button.
// these were just testing - use the "select photo" browser to select one
const char *img[5] =
{
"/home/raster/t1.jpg", // 5 mpixel
@ -67,6 +112,7 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
ph = elm_photocam_add(win);
evas_object_size_hint_weight_set(ph, 1.0, 1.0);
elm_win_resize_object_add(win, ph);
evas_object_data_set(ph, "window", win);
elm_photocam_file_set(ph, img[1]);
@ -84,6 +130,14 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
elm_table_pack(tb2, bt, 0, 0, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
elm_button_label_set(bt, "Select Photo");
evas_object_smart_callback_add(bt, "clicked", my_bt_open, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.5, 0.1);
elm_table_pack(tb2, bt, 1, 0, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
elm_button_label_set(bt, "Z +");
evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_in, ph);
@ -91,13 +145,31 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
evas_object_size_hint_align_set(bt, 0.9, 0.1);
elm_table_pack(tb2, bt, 2, 0, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
elm_button_label_set(bt, "Show 30,50 500x300");
evas_object_smart_callback_add(bt, "clicked", my_bt_show_reg, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.1, 0.5);
elm_table_pack(tb2, bt, 0, 1, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
elm_button_label_set(bt, "Bring 800,300 500x300");
evas_object_smart_callback_add(bt, "clicked", my_bt_bring_reg, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.9, 0.5);
elm_table_pack(tb2, bt, 2, 1, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
elm_button_label_set(bt, "Manual");
evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_man, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.1, 0.9);
elm_table_pack(tb2, bt, 0, 1, 1, 1);
elm_table_pack(tb2, bt, 0, 2, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
@ -105,7 +177,7 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fit, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.5, 0.9);
elm_table_pack(tb2, bt, 1, 1, 1, 1);
elm_table_pack(tb2, bt, 1, 2, 1, 1);
evas_object_show(bt);
bt = elm_button_add(win);
@ -113,7 +185,7 @@ test_photocam(void *data, Evas_Object *obj, void *event_info)
evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_fill, ph);
evas_object_size_hint_weight_set(bt, 1.0, 1.0);
evas_object_size_hint_align_set(bt, 0.9, 0.9);
elm_table_pack(tb2, bt, 2, 1, 1, 1);
elm_table_pack(tb2, bt, 2, 2, 1, 1);
evas_object_show(bt);
evas_object_show(tb2);

View File

@ -884,7 +884,21 @@ extern "C" {
EAPI void elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode);
EAPI Elm_Photocam_Zoom_Mode elm_photocam_zoom_mode_get(Evas_Object *obj);
EAPI void elm_photocam_image_size_get(Evas_Object *obj, int *w, int *h);
EAPI void elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h);
EAPI void elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h);
/* smart callbacks called:
* "clicked" - when image clicked
* "press" - when mouse/finger held down initially on image
* "longpressed" - when mouse/finger held for long time on image
* "clicked,double" - when mouse/finger double-clicked
* "load" - when photo load begins
* "loaded" - when photo load done
* "load,details" - when detailed image load begins
* "loaded,details" - when detailed image load done
* "zoom,start" - when zooming started
* "zoom,stop" - when zooming stopped
* "zoom,change" - when auto zoom mode changed zoom level
*/
#ifdef __cplusplus
}
#endif

View File

@ -6,28 +6,46 @@
*
* This is a widget specifically for displaying high-resolution digital
* camera photos giving speedy feedback (fast load), low memory footprint
* and zooming and panning as well as fitting logic.
* and zooming and panning as well as fitting logic. It is entirely focused
* on jpeg images, and takes advantage of properties of the jpeg format (via
* evas loader features in the jpeg loader).
*
* TODO:
*
* 1. clicked signal - get mouse down/up etc. on photo
* 2. longpress signal "
* 3. wrap photo in theme edje so u can have styling around photo
* 4. handle styles properly
* 5. signals for stages of load (main preload, each tile, all done)
* 6. signals for change in zoom level
* 7. signals for change in pan
* 8. controls for setting panning
*
* optional?
*
* 9. exif handling
* 10. rotation flags in exif handling (nasty! should have rot in evas)
*
* Signals that you can add callbacks for are:
*
* clicked - This is called when a user has double-clicked an item. The
* event_info parameter is the genlist item that was double-clicked.
* clicked - This is called when a user has clicked the photo without dragging
* around.
*
* press - This is called when a user has pressed down on the photo.
*
* longpressed - This is called when a user has pressed down on the photo for
* a long time without dragging around.
*
* clicked,double - This is called when a user has double-clicked the photo.
*
* load - Photo load begins.
*
* loaded - This is called when the image file load is complete for the first
* view (low resolution blurry version).
*
* load,details - Photo detailed data load begins.
*
* loaded,details - This is called when the image file load is complete for the
* detailed image data (full resolution needed).
*
* zoom,start - Zoom animation started.
*
* zoom,stop - Zoom animation stopped.
*
* zoom,change - Zoom changed when using an auto zoom mode.
*
* ---
*
* TODO (maybe - optional future stuff):
*
* 1. wrap photo in theme edje so u can have styling around photo (like white
* photo bordering).
* 2. exif handling
* 3. rotation flags in exif handling (nasty! should have rot in evas)
*
*/
typedef struct _Widget_Data Widget_Data;
@ -38,14 +56,13 @@ typedef struct _Grid_Item Grid_Item;
struct _Grid_Item
{
Widget_Data *wd;
Evas_Object *img;
struct {
int x, y, w, h;
} src, out;
Eina_Bool want : 1;
Eina_Bool have : 1;
Eina_Bool want_new : 1;
Eina_Bool have_new : 1;
};
struct _Grid
@ -73,6 +90,7 @@ struct _Widget_Data
Ecore_Job *calc_job;
Ecore_Timer *scr_timer;
Ecore_Timer *long_timer;
Ecore_Animator *zoom_animator;
double t_start, t_end;
struct {
@ -86,9 +104,12 @@ struct _Widget_Data
int tsize;
Evas_Object *img; // low res version of image (scale down == 8)
int nosmooth;
int preload_num;
Eina_List *grids;
Eina_Bool main_load_pending : 1;
Eina_Bool resized : 1;
Eina_Bool longpressed : 1;
Eina_Bool on_hold : 1;
};
struct _Pan
@ -105,7 +126,7 @@ static void _sizing_eval(Evas_Object *obj);
static void _calc_job(void *data);
static void grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
static void grid_clear(Grid *g);
static void grid_clear(Evas_Object *obj, Grid *g);
static Grid *grid_create(Evas_Object *obj);
static void grid_load(Evas_Object *obj, Grid *g);
@ -152,13 +173,13 @@ grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord o
yy = g->grid[tn].out.y;
ww = g->grid[tn].out.w;
hh = g->grid[tn].out.h;
if (gw != g->w)
if ((gw != g->w) && (g->w > 0))
{
tx = xx;
xx = (gw * xx) / g->w;
ww = ((gw * (tx + ww)) / g->w) - xx;
}
if (gh != g->h)
if ((gh != g->h) && (g->h > 0))
{
ty = yy;
yy = (gh * yy) / g->h;
@ -174,8 +195,9 @@ grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord o
}
static void
grid_clear(Grid *g)
grid_clear(Evas_Object *obj, Grid *g)
{
Widget_Data *wd = elm_widget_data_get(obj);
int x, y;
if (!g->grid) return;
@ -187,6 +209,16 @@ grid_clear(Grid *g)
tn = (y * g->gw) + x;
evas_object_del(g->grid[tn].img);
if (g->grid[tn].want)
{
wd->preload_num--;
if (wd->preload_num == 0)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
"elm,state,busy,stop", "elm");
evas_object_smart_callback_call(obj, "loaded,detail", NULL);
}
}
}
}
free(g->grid);
@ -200,8 +232,19 @@ _tile_preloaded(void *data, Evas *e, Evas_Object *o, void *event_info)
{
Grid_Item *git = data;
evas_object_show(git->img);
git->have = 1;
if (git->want)
{
git->want = 0;
evas_object_show(git->img);
git->have = 1;
git->wd->preload_num--;
if (git->wd->preload_num == 0)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(git->wd->scr),
"elm,state,busy,stop", "elm");
evas_object_smart_callback_call(git->wd->obj, "loaded,detail", NULL);
}
}
}
static Grid *
@ -253,8 +296,10 @@ grid_create(Evas_Object *obj)
g->grid[tn].out.w = g->grid[tn].src.w;
g->grid[tn].out.h = g->grid[tn].src.h;
g->grid[tn].wd = wd;
g->grid[tn].img =
evas_object_image_add(evas_object_evas_get(obj));
evas_object_pass_events_set(g->grid[tn].img, 1);
evas_object_image_scale_hint_set(g->grid[tn].img, EVAS_IMAGE_SCALE_HINT_STATIC);
evas_object_smart_member_add(g->grid[tn].img,
wd->pan_smart);
@ -274,25 +319,45 @@ grid_load(Evas_Object *obj, Grid *g)
{
Widget_Data *wd = elm_widget_data_get(obj);
int x, y;
Evas_Coord ow, oh;
Evas_Coord ow, oh, gw, gh, ax, ay, tx, ty;
elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
ax = 0;
ay = 0;
gw = wd->size.w;
gh = wd->size.h;
if (ow > gw) ax = (ow - gw) / 2;
if (oh > gh) ay = (oh - gh) / 2;
for (y = 0; y < g->gh; y++)
{
for (x = 0; x < g->gw; x++)
{
int tn;
int tn, xx, yy, ww, hh;
Eina_Bool visible = 0;
tn = (y * g->gw) + x;
if (ELM_RECTS_INTERSECT(wd->pan_x, wd->pan_y,
ow, oh,
g->grid[tn].out.x,
g->grid[tn].out.y,
g->grid[tn].out.w,
g->grid[tn].out.h))
xx = g->grid[tn].out.x;
yy = g->grid[tn].out.y;
ww = g->grid[tn].out.w;
hh = g->grid[tn].out.h;
if ((gw != g->w) && (g->w > 0))
{
tx = xx;
xx = (gw * xx) / g->w;
ww = ((gw * (tx + ww)) / g->w) - xx;
}
if ((gh != g->h) && (g->h > 0))
{
ty = yy;
yy = (gh * yy) / g->h;
hh = ((gh * (ty + hh)) / g->h) - yy;
}
// xx += ax;
// yy += ay;
if (ELM_RECTS_INTERSECT(wd->pan_x, wd->pan_y, ow, oh,
xx, yy, ww, hh))
visible = 1;
if ((visible) && (!g->grid[tn].want))
if ((visible) && (!g->grid[tn].have) && (!g->grid[tn].want))
{
g->grid[tn].want = 1;
evas_object_hide(g->grid[tn].img);
@ -305,10 +370,30 @@ grid_load(Evas_Object *obj, Grid *g)
g->grid[tn].src.h);
evas_object_image_file_set(g->grid[tn].img, wd->file, NULL);
evas_object_image_preload(g->grid[tn].img, 0);
wd->preload_num++;
if (wd->preload_num == 1)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
"elm,state,busy,start", "elm");
evas_object_smart_callback_call(obj, "load,detail", NULL);
}
}
else if ((g->grid[tn].want) && (!visible))
{
wd->preload_num--;
if (wd->preload_num == 0)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
"elm,state,busy,stop", "elm");
evas_object_smart_callback_call(obj, "loaded,detail", NULL);
}
g->grid[tn].want = 0;
evas_object_hide(g->grid[tn].img);
evas_object_image_preload(g->grid[tn].img, 1);
evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
}
else if ((g->grid[tn].have) && (!visible))
{
g->grid[tn].have = 0;
evas_object_hide(g->grid[tn].img);
evas_object_image_preload(g->grid[tn].img, 1);
@ -326,7 +411,7 @@ grid_clearall(Evas_Object *obj)
EINA_LIST_FREE(wd->grids, g)
{
grid_clear(g);
grid_clear(obj, g);
free(g);
}
}
@ -408,9 +493,18 @@ _main_preloaded(void *data, Evas *e, Evas_Object *o, void *event_info)
if (g)
{
wd->grids = eina_list_prepend(wd->grids, g);
grid_load(wd->obj, g);
}
if (wd->calc_job) ecore_job_del(wd->calc_job);
wd->calc_job = ecore_job_add(_calc_job, wd);
evas_object_smart_callback_call(data, "loaded", NULL);
wd->preload_num--;
if (wd->preload_num == 0)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
"elm,state,busy,stop", "elm");
evas_object_smart_callback_call(obj, "loaded,detail", NULL);
}
}
static int
@ -426,7 +520,10 @@ _zoom_anim(void *data)
{
t = 1.0;
}
else t = (t - wd->t_start) / (wd->t_end - wd->t_start);
else if (wd->t_end > wd->t_start)
t = (t - wd->t_start) / (wd->t_end - wd->t_start);
else
t = 1.0;
t = 1.0 - t;
t = 1.0 - (t * t);
wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
@ -451,18 +548,71 @@ _zoom_anim(void *data)
if (g->dead)
{
wd->grids = eina_list_remove_list(wd->grids, l);
grid_clear(g);
grid_clear(data, g);
free(g);
}
}
wd->nosmooth--;
if (wd->nosmooth == 0) _smooth_update(data);
wd->zoom_animator = NULL;
evas_object_smart_callback_call(data, "zoom,stop", NULL);
return 0;
}
return 1;
}
static void
_mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Move *ev = event_info;
}
static int
_long_press(void *data)
{
Widget_Data *wd = elm_widget_data_get(data);
wd->long_timer = NULL;
wd->longpressed = EINA_TRUE;
evas_object_smart_callback_call(data, "longpressed", NULL);
return 0;
}
static void
_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Down *ev = event_info;
if (ev->button != 1) return;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
else wd->on_hold = EINA_FALSE;
if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
evas_object_smart_callback_call(data, "clicked,double", NULL);
else
evas_object_smart_callback_call(data, "press", NULL);
wd->longpressed = EINA_FALSE;
if (wd->long_timer) ecore_timer_del(wd->long_timer);
wd->long_timer = ecore_timer_add(1.0, _long_press, data);
}
static void
_mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Up *ev = event_info;
if (ev->button != 1) return;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
else wd->on_hold = EINA_FALSE;
if (wd->long_timer)
{
ecore_timer_del(wd->long_timer);
wd->long_timer = NULL;
}
if (!wd->on_hold)
evas_object_smart_callback_call(data, "clicked", NULL);
wd->on_hold = EINA_FALSE;
}
static Evas_Smart_Class _pan_sc = {NULL};
static void
@ -482,6 +632,7 @@ _del_hook(Evas_Object *obj)
if (wd->calc_job) ecore_job_del(wd->calc_job);
if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
if (wd->long_timer) ecore_timer_del(wd->long_timer);
free(wd);
}
@ -489,7 +640,7 @@ static void
_theme_hook(Evas_Object *obj)
{
Widget_Data *wd = elm_widget_data_get(obj);
elm_smart_scroller_theme_set(wd->scr, "scroller", "base", elm_widget_style_get(obj));
elm_smart_scroller_theme_set(wd->scr, "photocam", "base", elm_widget_style_get(obj));
edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
_sizing_eval(obj);
}
@ -700,6 +851,7 @@ elm_photocam_add(Evas_Object *parent)
elm_widget_theme_hook_set(obj, _theme_hook);
wd->scr = elm_smart_scroller_add(e);
elm_smart_scroller_theme_set(wd->scr, "photocam", "base", "default");
evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
elm_widget_resize_object_set(obj, wd->scr);
@ -744,6 +896,12 @@ elm_photocam_add(Evas_Object *parent)
wd->tsize = 512;
wd->img = evas_object_image_add(e);
evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
_mouse_down, obj);
evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
_mouse_up, obj);
evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_MOVE,
_mouse_move, obj);
evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_STATIC);
evas_object_smart_member_add(wd->img, wd->pan_smart);
elm_widget_sub_object_add(obj, wd->img);
@ -809,6 +967,16 @@ elm_photocam_file_set(Evas_Object *obj, const char *file)
grid_clearall(obj);
if (wd->calc_job) ecore_job_del(wd->calc_job);
wd->calc_job = ecore_job_add(_calc_job, wd);
evas_object_smart_callback_call(obj, "load", NULL);
wd->preload_num++;
if (wd->preload_num == 1)
{
edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
"elm,state,busy,start", "elm");
evas_object_smart_callback_call(obj, "load,detail", NULL);
}
wd->zoom++;
elm_photocam_zoom_set(obj, wd->zoom - 1);
return evas_object_image_load_error_get(wd->img);
}
@ -833,6 +1001,7 @@ elm_photocam_zoom_set(Evas_Object *obj, int zoom)
Grid *g, *g_zoom = NULL;
Evas_Coord pw, ph, rx, ry, rw, rh;
int z;
int zoom_changed = 0, started = 0;
Ecore_Animator *an;
if (zoom < 1) zoom = 1;
@ -849,56 +1018,74 @@ elm_photocam_zoom_set(Evas_Object *obj, int zoom)
}
else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT)
{
ph = (wd->size.imh * rw) / wd->size.imw;
if (ph > rh)
if ((wd->size.imw < 1) || (wd->size.imh < 1))
{
pw = (wd->size.imw * rh) / wd->size.imh;
ph = rh;
wd->size.nw = 0;
wd->size.nw = 0;
}
else
{
pw = rw;
ph = (wd->size.imh * rw) / wd->size.imw;
if (ph > rh)
{
pw = (wd->size.imw * rh) / wd->size.imh;
ph = rh;
}
else
{
pw = rw;
}
if ((pw > wd->size.imw) || (ph > wd->size.imh))
{
pw = wd->size.imw;
ph = wd->size.imh;
}
if (wd->size.imw > wd->size.imh)
z = wd->size.imw / pw;
else
z = wd->size.imh / ph;
if (z >= 8) z = 8;
else if (z >= 4) z = 4;
else if (z >= 2) z = 2;
else z = 1;
if (z != wd->zoom) zoom_changed = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
}
if ((pw > wd->size.imw) || (ph > wd->size.imh))
{
pw = wd->size.imw;
ph = wd->size.imh;
}
if (wd->size.imw > wd->size.imh)
z = wd->size.imw / pw;
else
z = wd->size.imh / ph;
if (z >= 8) z = 8;
else if (z >= 4) z = 4;
else if (z >= 2) z = 2;
else z = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
}
else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL)
{
ph = (wd->size.imh * rw) / wd->size.imw;
if (ph < rh)
if ((wd->size.imw < 1) || (wd->size.imh < 1))
{
pw = (wd->size.imw * rh) / wd->size.imh;
ph = rh;
wd->size.nw = 0;
wd->size.nw = 0;
}
else
{
pw = rw;
ph = (wd->size.imh * rw) / wd->size.imw;
if (ph < rh)
{
pw = (wd->size.imw * rh) / wd->size.imh;
ph = rh;
}
else
{
pw = rw;
}
if (wd->size.imw > wd->size.imh)
z = wd->size.imw / pw;
else
z = wd->size.imh / ph;
if (z >= 8) z = 8;
else if (z >= 4) z = 4;
else if (z >= 2) z = 2;
else z = 1;
if (z != wd->zoom) zoom_changed = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
}
if (wd->size.imw > wd->size.imh)
z = wd->size.imw / pw;
else
z = wd->size.imh / ph;
if (z >= 8) z = 8;
else if (z >= 4) z = 4;
else if (z >= 2) z = 2;
else z = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
}
if (wd->main_load_pending)
{
@ -935,19 +1122,38 @@ elm_photocam_zoom_set(Evas_Object *obj, int zoom)
wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
wd->nosmooth++;
if (wd->nosmooth == 1) _smooth_update(obj);
started = 1;
}
wd->t_start = ecore_loop_time_get();
wd->t_end = wd->t_start + _elm_config->zoom_friction;
wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.w;
wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.h;
if ((wd->size.w > 0) && (wd->size.h > 0))
{
wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.w;
wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.h;
}
else
{
wd->size.spos.x = 0.5;
wd->size.spos.y = 0.5;
}
if (rw > wd->size.w) wd->size.spos.x = 0.5;
if (rh > wd->size.h) wd->size.spos.y = 0.5;
if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
an = wd->zoom_animator;
if (!_zoom_anim(obj)) ecore_animator_del(an);
if (!_zoom_anim(obj))
{
ecore_animator_del(an);
an = NULL;
}
if (wd->calc_job) ecore_job_del(wd->calc_job);
wd->calc_job = ecore_job_add(_calc_job, wd);
if (started)
evas_object_smart_callback_call(obj, "zoom,start", NULL);
if (!an)
evas_object_smart_callback_call(obj, "zoom,stop", NULL);
if (zoom_changed)
evas_object_smart_callback_call(obj, "zoom,change", NULL);
}
/**
@ -1035,3 +1241,79 @@ elm_photocam_image_size_get(Evas_Object *obj, int *w, int *h)
if (w) *w = wd->size.imw;
if (h) *h = wd->size.imh;
}
/**
* Set the viewed portion of the image
*
* This sets the region of the image to be viewed
*
* @param obj The photocam object
* @param x X-coordinate of region in image original pixels
* @param y Y-coordinate of region in image original pixels
* @param w Width of region in image original pixels
* @param h Height of region in image original pixels
*
* @ingroup Photocam
*/
EAPI void
elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h)
{
Widget_Data *wd = elm_widget_data_get(obj);
int rx, ry, rw, rh;
if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
rx = (x * wd->size.w) / wd->size.imw;
ry = (y * wd->size.h) / wd->size.imh;
rw = (w * wd->size.w) / wd->size.imw;
rh = (w * wd->size.h) / wd->size.imh;
if (rw < 1) rw = 1;
if (rh < 1) rh = 1;
if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
if (wd->zoom_animator)
{
wd->nosmooth--;
if (wd->nosmooth == 0) _smooth_update(obj);
ecore_animator_del(wd->zoom_animator);
wd->zoom_animator = NULL;
}
elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
}
/**
* Bring in the viewed portion of the image
*
* This brings in the region of the image over time
*
* @param obj The photocam object
* @param x X-coordinate of region in image original pixels
* @param y Y-coordinate of region in image original pixels
* @param w Width of region in image original pixels
* @param h Height of region in image original pixels
*
* @ingroup Photocam
*/
EAPI void
elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h)
{
Widget_Data *wd = elm_widget_data_get(obj);
int rx, ry, rw, rh;
if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
rx = (x * wd->size.w) / wd->size.imw;
ry = (y * wd->size.h) / wd->size.imh;
rw = (w * wd->size.w) / wd->size.imw;
rh = (w * wd->size.h) / wd->size.imh;
if (rw < 1) rw = 1;
if (rh < 1) rh = 1;
if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
if (wd->zoom_animator)
{
wd->nosmooth--;
if (wd->nosmooth == 0) _smooth_update(obj);
ecore_animator_del(wd->zoom_animator);
wd->zoom_animator = NULL;
}
elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
}