1 /* 2 * Copyright (C) 2007 Holger Hans Peter Freyther zecke (at) 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 45 PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize size) 46 { 47 return adoptRef(new ScrollbarEfl(scrollableArea, orientation, size)); 48 } 49 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 59 ScrollbarEfl::~ScrollbarEfl() 60 { 61 if (!evasObject()) 62 return; 63 evas_object_del(evasObject()); 64 setEvasObject(0); 65 } 66 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 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 143 void ScrollbarEfl::updateThumbPosition() 144 { 145 updateThumbPositionAndProportion(); 146 } 147 148 void ScrollbarEfl::updateThumbProportion() 149 { 150 updateThumbPositionAndProportion(); 151 } 152 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 188 void ScrollbarEfl::setFrameRect(const IntRect& rect) 189 { 190 Widget::setFrameRect(rect); 191 frameRectsChanged(); 192 } 193 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 213 void ScrollbarEfl::paint(GraphicsContext* graphicsContext, const IntRect& damageRect) 214 { 215 } 216 217