1 /*
2 * Copyright (C) 2007 Holger Hans Peter Freyther zecke@selfish.org
3 * (C) 2009 Kenneth Rohde Christiansen
4 * (C) 2009 INdT, Instituto Nokia de Technologia
5 * (C) 2009-2010 ProFUSION embedded systems
6 * (C) 2009-2010 Samsung Electronics
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "config.h"
24 #include "ScrollbarEfl.h"
25
26 #include "ChromeClient.h"
27 #include "Frame.h"
28 #include "FrameView.h"
29 #include "GraphicsContext.h"
30 #include "HostWindow.h"
31 #include "IntRect.h"
32 #include "NotImplemented.h"
33 #include "Page.h"
34 #include "ScrollbarTheme.h"
35
36 #include <Ecore.h>
37 #include <Edje.h>
38 #include <Evas.h>
39 #include <string>
40 #include <wtf/text/CString.h>
41
42 using namespace std;
43 using namespace WebCore;
44
createNativeScrollbar(ScrollableArea * scrollableArea,ScrollbarOrientation orientation,ScrollbarControlSize size)45 PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize size)
46 {
47 return adoptRef(new ScrollbarEfl(scrollableArea, orientation, size));
48 }
49
ScrollbarEfl(ScrollableArea * scrollableArea,ScrollbarOrientation orientation,ScrollbarControlSize controlSize)50 ScrollbarEfl::ScrollbarEfl(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
51 : Scrollbar(scrollableArea, orientation, controlSize)
52 , m_lastPos(0)
53 , m_lastTotalSize(0)
54 , m_lastVisibleSize(0)
55 {
56 Widget::setFrameRect(IntRect(0, 0, 0, 0));
57 }
58
~ScrollbarEfl()59 ScrollbarEfl::~ScrollbarEfl()
60 {
61 if (!evasObject())
62 return;
63 evas_object_del(evasObject());
64 setEvasObject(0);
65 }
66
scrollbarEflEdjeMessage(void * data,Evas_Object * object,Edje_Message_Type messageType,int id,void * message)67 static void scrollbarEflEdjeMessage(void* data, Evas_Object* object, Edje_Message_Type messageType, int id, void* message)
68 {
69 ScrollbarEfl* that = static_cast<ScrollbarEfl*>(data);
70 Edje_Message_Float* messageFloat;
71 int value;
72
73 if (!id) {
74 EINA_LOG_ERR("Unknown message id '%d' from scroll bar theme.", id);
75 return;
76 }
77
78 if (messageType != EDJE_MESSAGE_FLOAT) {
79 EINA_LOG_ERR("Message id '%d' of incorrect type from scroll bar theme. "
80 "Expected '%d', got '%d'.",
81 id, EDJE_MESSAGE_FLOAT, messageType);
82 return;
83 }
84
85 messageFloat = static_cast<Edje_Message_Float*>(message);
86 value = messageFloat->val * (that->totalSize() - that->visibleSize());
87 that->scrollableArea()->scrollToOffsetWithoutAnimation(that->orientation(), value);
88 }
89
setParent(ScrollView * view)90 void ScrollbarEfl::setParent(ScrollView* view)
91 {
92 Evas_Object* object = evasObject();
93 Evas_Coord w, h;
94
95 Widget::setParent(view);
96
97 if (!object) {
98 if (!view)
99 return;
100
101 object = edje_object_add(view->evas());
102 if (!object) {
103 EINA_LOG_ERR("Could not create edje object for view=%p (evas=%p)",
104 view, view->evas());
105 return;
106 }
107 edje_object_message_handler_set(object, scrollbarEflEdjeMessage, this);
108 setEvasObject(object);
109 } else if (!view) {
110 evas_object_hide(object);
111 return;
112 }
113
114 const char* group = (orientation() == HorizontalScrollbar)
115 ? "scrollbar.horizontal" : "scrollbar.vertical";
116 String theme(edjeThemeRecursive());
117
118 if (theme.isEmpty()) {
119 EINA_LOG_ERR("Could not load theme '%s': no theme path set.", group);
120 evas_object_hide(object);
121 return;
122 }
123
124 if (!edje_object_file_set(object, theme.utf8().data(), group)) {
125 Edje_Load_Error err = edje_object_load_error_get(object);
126 const char* errmessage = edje_load_error_str(err);
127 EINA_LOG_ERR("Could not load theme '%s' from file '%s': #%d '%s'",
128 group, theme.utf8().data(), err, errmessage);
129 return;
130 }
131
132 setPlatformWidget(object);
133 evas_object_smart_member_add(object, view->evasObject());
134 evas_object_show(object);
135
136 edje_object_size_min_get(object, &w, &h);
137
138 IntRect rect = frameRect();
139 rect.setSize(IntSize(w, h));
140 setFrameRect(rect);
141 }
142
updateThumbPosition()143 void ScrollbarEfl::updateThumbPosition()
144 {
145 updateThumbPositionAndProportion();
146 }
147
updateThumbProportion()148 void ScrollbarEfl::updateThumbProportion()
149 {
150 updateThumbPositionAndProportion();
151 }
152
updateThumbPositionAndProportion()153 void ScrollbarEfl::updateThumbPositionAndProportion()
154 {
155 if (!platformWidget())
156 return;
157
158 int pos = currentPos();
159 int tSize = totalSize();
160 int vSize = visibleSize();
161
162 if (m_lastPos == pos
163 && m_lastTotalSize == tSize
164 && m_lastVisibleSize == vSize)
165 return;
166
167 m_lastPos = pos;
168 m_lastTotalSize = tSize;
169 m_lastVisibleSize = vSize;
170
171 Edje_Message_Float_Set* message = static_cast<Edje_Message_Float_Set*>
172 (alloca(sizeof(Edje_Message_Float_Set) + sizeof(float)));
173 message->count = 2;
174
175 if (tSize - vSize > 0)
176 message->val[0] = pos / static_cast<float>(tSize - vSize);
177 else
178 message->val[0] = 0.0;
179
180 if (tSize > 0)
181 message->val[1] = vSize / static_cast<float>(tSize);
182 else
183 message->val[1] = 0.0;
184
185 edje_object_message_send(platformWidget(), EDJE_MESSAGE_FLOAT_SET, 0, message);
186 }
187
setFrameRect(const IntRect & rect)188 void ScrollbarEfl::setFrameRect(const IntRect& rect)
189 {
190 Widget::setFrameRect(rect);
191 frameRectsChanged();
192 }
193
frameRectsChanged()194 void ScrollbarEfl::frameRectsChanged()
195 {
196 Evas_Object* object = platformWidget();
197 Evas_Coord x, y;
198
199 if (!parent() || !object)
200 return;
201
202 IntRect rect = frameRect();
203 if (parent()->isScrollViewScrollbar(this))
204 rect.setLocation(parent()->convertToContainingWindow(rect.location()));
205 else
206 rect.setLocation(parent()->contentsToWindow(rect.location()));
207
208 evas_object_geometry_get(root()->evasObject(), &x, &y, 0, 0);
209 evas_object_move(object, x + rect.x(), y + rect.y());
210 evas_object_resize(object, rect.width(), rect.height());
211 }
212
paint(GraphicsContext * graphicsContext,const IntRect & damageRect)213 void ScrollbarEfl::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
214 {
215 }
216
217