001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.gwt.client.ui; 029 030import org.opencms.gwt.client.dnd.CmsDNDHandler; 031import org.opencms.gwt.client.dnd.CmsDNDHandler.Orientation; 032import org.opencms.gwt.client.dnd.I_CmsDraggable; 033import org.opencms.gwt.client.dnd.I_CmsDropTarget; 034import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 035import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.I_CmsListTreeCss; 036import org.opencms.gwt.client.util.CmsDomUtil; 037 038import java.util.HashMap; 039import java.util.Map; 040 041import com.google.gwt.dom.client.Element; 042import com.google.gwt.user.client.DOM; 043import com.google.gwt.user.client.ui.ComplexPanel; 044import com.google.gwt.user.client.ui.Widget; 045 046/** 047 * A very basic list implementation to hold {@link CmsListItemWidget}.<p> 048 * 049 * @param <I> the specific list item implementation 050 * 051 * @since 8.0.0 052 */ 053public class CmsList<I extends I_CmsListItem> extends ComplexPanel implements I_CmsTruncable, I_CmsDropTarget { 054 055 /** The css bundle used for this widget. */ 056 private static final I_CmsListTreeCss CSS = I_CmsLayoutBundle.INSTANCE.listTreeCss(); 057 058 /** The drag'n drop handler. */ 059 protected CmsDNDHandler m_dndHandler; 060 061 /** The current place holder. */ 062 protected Element m_placeholder; 063 064 /** The placeholder position index. */ 065 protected int m_placeholderIndex = -1; 066 067 /** The child width in px for truncation. */ 068 private int m_childWidth; 069 070 /** Flag to indicate if drag'n drop on the root node is allowed. */ 071 private boolean m_dropEnabled; 072 073 /** The map of items. */ 074 private Map<String, I> m_items; 075 076 /** Flag to indicate if the list will always return <code>true</code> on check target requests within drag and drop. */ 077 private boolean m_takeAll; 078 079 /** The text metrics prefix. */ 080 private String m_tmPrefix; 081 082 /** 083 * Constructor.<p> 084 */ 085 public CmsList() { 086 087 setElement((Element)DOM.createElement(CmsDomUtil.Tag.ul.name())); 088 setStyleName(CSS.list()); 089 m_items = new HashMap<String, I>(); 090 } 091 092 /** 093 * @see com.google.gwt.user.client.ui.Panel#add(com.google.gwt.user.client.ui.Widget) 094 */ 095 @SuppressWarnings("unchecked") 096 @Override 097 public void add(Widget widget) { 098 099 assert widget instanceof I_CmsListItem; 100 add(widget, (Element)getElement()); 101 registerItem((I)widget); 102 } 103 104 /** 105 * Adds an item to the list.<p> 106 * 107 * @param item the item to add 108 * 109 * @see #add(Widget) 110 */ 111 public void addItem(I item) { 112 113 add((Widget)item); 114 } 115 116 /** 117 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#checkPosition(int, int, Orientation) 118 */ 119 public boolean checkPosition(int x, int y, Orientation orientation) { 120 121 if (!isDropEnabled()) { 122 return false; 123 } 124 if (isDNDTakeAll()) { 125 return true; 126 } 127 switch (orientation) { 128 case HORIZONTAL: 129 return CmsDomUtil.checkPositionInside(getElement(), x, -1); 130 case VERTICAL: 131 return CmsDomUtil.checkPositionInside(getElement(), -1, y); 132 case ALL: 133 default: 134 return CmsDomUtil.checkPositionInside(getElement(), x, y); 135 } 136 } 137 138 /** 139 * Clears the list.<p> 140 */ 141 public void clearList() { 142 143 clear(); 144 m_items.clear(); 145 } 146 147 /** 148 * Returns the drag'n drop handler.<p> 149 * 150 * @return the handler 151 */ 152 public CmsDNDHandler getDnDHandler() { 153 154 return m_dndHandler; 155 } 156 157 /** 158 * Returns the list item at the given position.<p> 159 * 160 * @param index the position 161 * 162 * @return the list item 163 * 164 * @see #getWidget(int) 165 */ 166 public I getItem(int index) { 167 168 return (I)getWidget(index); 169 } 170 171 /** 172 * Returns the list item with the given id.<p> 173 * 174 * @param itemId the id of the item to retrieve 175 * 176 * @return the list item 177 * 178 * @see #getWidget(int) 179 */ 180 public I getItem(String itemId) { 181 182 return m_items.get(itemId); 183 } 184 185 /** 186 * Returns the given item position.<p> 187 * 188 * @param item the item to get the position for 189 * 190 * @return the item position 191 */ 192 public int getItemPosition(I item) { 193 194 return getWidgetIndex((Widget)item); 195 } 196 197 /** 198 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#getPlaceholderIndex() 199 */ 200 public int getPlaceholderIndex() { 201 202 return m_placeholderIndex; 203 204 } 205 206 /** 207 * Inserts the given widget at the given position.<p> 208 * 209 * @param widget the widget to insert 210 * @param position the position 211 */ 212 @SuppressWarnings("unchecked") 213 public void insert(Widget widget, int position) { 214 215 assert widget instanceof I_CmsListItem; 216 insert(widget, (Element)getElement(), position, true); 217 registerItem((I)widget); 218 } 219 220 /** 221 * Inserts the given item at the given position.<p> 222 * 223 * @param item the item to insert 224 * @param position the position 225 */ 226 public void insertItem(I item, int position) { 227 228 insert((Widget)item, position); 229 } 230 231 /** 232 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#insertPlaceholder(com.google.gwt.dom.client.Element, int, int, Orientation) 233 */ 234 public void insertPlaceholder(Element placeholder, int x, int y, Orientation orientation) { 235 236 m_placeholder = placeholder; 237 repositionPlaceholder(x, y, orientation); 238 } 239 240 /** 241 * Returns if the list will always return <code>true</code> on check target requests within drag and drop.<p> 242 * 243 * @return <code>true</code> if take all is enabled for drag and drop 244 */ 245 public boolean isDNDTakeAll() { 246 247 return m_takeAll; 248 } 249 250 /** 251 * Checks if dropping is enabled.<p> 252 * 253 * @return <code>true</code> if dropping is enabled 254 */ 255 public boolean isDropEnabled() { 256 257 return m_dropEnabled; 258 } 259 260 /** 261 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#onDrop(org.opencms.gwt.client.dnd.I_CmsDraggable) 262 */ 263 public void onDrop(I_CmsDraggable draggable) { 264 265 return; 266 } 267 268 /** 269 * @see com.google.gwt.user.client.ui.ComplexPanel#remove(com.google.gwt.user.client.ui.Widget) 270 */ 271 @Override 272 public boolean remove(Widget w) { 273 274 boolean result = super.remove(w); 275 if (result && (w instanceof I_CmsListItem)) { 276 String id = ((I_CmsListItem)w).getId(); 277 if (id != null) { 278 m_items.remove(id); 279 } 280 } 281 return result; 282 } 283 284 /** 285 * Removes an item from the list.<p> 286 * 287 * @param item the item to remove 288 * 289 * @return the removed item 290 * 291 * @see #remove(Widget) 292 */ 293 public I removeItem(I item) { 294 295 remove((Widget)item); 296 return item; 297 } 298 299 /** 300 * Removes an item from the list.<p> 301 * 302 * @param itemId the id of the item to remove 303 * 304 * @return the removed item 305 * 306 * @see #remove(Widget) 307 */ 308 public I removeItem(String itemId) { 309 310 I item = m_items.get(itemId); 311 remove((Widget)item); 312 return item; 313 } 314 315 /** 316 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#removePlaceholder() 317 */ 318 public void removePlaceholder() { 319 320 if (m_placeholder == null) { 321 return; 322 } 323 m_placeholder.removeFromParent(); 324 m_placeholder = null; 325 m_placeholderIndex = -1; 326 } 327 328 /** 329 * @see org.opencms.gwt.client.dnd.I_CmsDropTarget#repositionPlaceholder(int, int, Orientation) 330 */ 331 public void repositionPlaceholder(int x, int y, Orientation orientation) { 332 333 switch (orientation) { 334 case HORIZONTAL: 335 m_placeholderIndex = CmsDomUtil.positionElementInside( 336 m_placeholder, 337 getElement(), 338 m_placeholderIndex, 339 x, 340 -1); 341 break; 342 case VERTICAL: 343 m_placeholderIndex = CmsDomUtil.positionElementInside( 344 m_placeholder, 345 getElement(), 346 m_placeholderIndex, 347 -1, 348 y); 349 break; 350 case ALL: 351 default: 352 m_placeholderIndex = CmsDomUtil.positionElementInside( 353 m_placeholder, 354 getElement(), 355 m_placeholderIndex, 356 x, 357 y); 358 break; 359 } 360 } 361 362 /** 363 * Sets the drag'n drop handler.<p> 364 * 365 * @param handler the handler to set 366 */ 367 public void setDNDHandler(CmsDNDHandler handler) { 368 369 m_dndHandler = handler; 370 } 371 372 /** 373 * Sets if the list will always return <code>true</code> on check target requests within drag and drop.<p> 374 * 375 * @param takeAll <code>true</code> to enable take all for drag and drop 376 */ 377 public void setDNDTakeAll(boolean takeAll) { 378 379 m_takeAll = takeAll; 380 } 381 382 /** 383 * Enables/disables dropping.<p> 384 * 385 * @param enabled <code>true</code> to enable, or <code>false</code> to disable 386 */ 387 public void setDropEnabled(boolean enabled) { 388 389 m_dropEnabled = enabled; 390 } 391 392 /** 393 * @see org.opencms.gwt.client.ui.I_CmsTruncable#truncate(java.lang.String, int) 394 */ 395 public void truncate(String textMetricsPrefix, int widgetWidth) { 396 397 m_childWidth = widgetWidth; 398 for (Widget item : this) { 399 if (item instanceof I_CmsTruncable) { 400 ((I_CmsTruncable)item).truncate(textMetricsPrefix, widgetWidth); 401 } 402 } 403 m_tmPrefix = textMetricsPrefix; 404 } 405 406 /** 407 * Changes the id for the given item.<p> 408 * 409 * @param item the item to change the id for 410 * @param id the new id 411 */ 412 protected void changeId(I item, String id) { 413 414 if (m_items.remove(item.getId()) != null) { 415 m_items.put(id, item); 416 } 417 } 418 419 /** 420 * Registers the given item on this list.<p> 421 * 422 * @param item the item to register 423 */ 424 protected void registerItem(I item) { 425 426 if (item.getId() != null) { 427 m_items.put(item.getId(), item); 428 } 429 if (m_tmPrefix != null) { 430 item.truncate(m_tmPrefix, m_childWidth); 431 } 432 } 433 434 /** 435 * Sets the current drag'n drop place holder.<p> 436 * 437 * @param placeholder the element to set as place holder 438 */ 439 protected void setPlaceholder(Element placeholder) { 440 441 removePlaceholder(); 442 m_placeholder = placeholder; 443 } 444}