001package org.gwtbootstrap3.client.ui.base; 002 003/* 004 * #%L 005 * GwtBootstrap3 006 * %% 007 * Copyright (C) 2016 GwtBootstrap3 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import org.gwtbootstrap3.client.ui.base.helper.StyleHelper; 024import org.gwtbootstrap3.client.ui.base.mixin.IdMixin; 025import org.gwtbootstrap3.client.ui.base.mixin.PullMixin; 026import org.gwtbootstrap3.client.ui.constants.DeviceSize; 027import org.gwtbootstrap3.client.ui.constants.Pull; 028import org.gwtbootstrap3.client.ui.html.Text; 029 030import com.google.gwt.dom.client.Element; 031import com.google.gwt.dom.client.Style; 032import com.google.gwt.user.client.DOM; 033import com.google.gwt.user.client.ui.ComplexPanel; 034import com.google.gwt.user.client.ui.Widget; 035 036/** 037 * Base class for widgets that contain further widgets. 038 * 039 * @author Sven Jacobs 040 */ 041public class ComplexWidget extends ComplexPanel implements HasId, HasResponsiveness, HasInlineStyle, HasPull { 042 private final IdMixin<ComplexWidget> idMixin = new IdMixin<ComplexWidget>(this); 043 private final PullMixin<ComplexWidget> pullMixin = new PullMixin<ComplexWidget>(this); 044 045 /** 046 * {@inheritDoc} 047 */ 048 @Override 049 public void add(final Widget child) { 050 add(child, (Element) getElement()); 051 } 052 053 /** 054 * Inserts a widget at a specific index 055 * 056 * @param child - widget to be inserted 057 * @param beforeIndex - index for the widget 058 */ 059 public void insert(final Widget child, final int beforeIndex) { 060 insert(child, (Element) getElement(), beforeIndex, true); 061 } 062 063 @Override 064 @Deprecated 065 protected void insert(Widget child, com.google.gwt.user.client.Element container, 066 int beforeIndex, boolean domInsert) { 067 // Validate index; adjust if the widget is already a child of this panel. 068 beforeIndex = adjustIndex(child, beforeIndex); 069 070 // Detach new child. 071 child.removeFromParent(); 072 073 // Logical attach. 074 getChildren().insert(child, beforeIndex); 075 076 // Physical attach. 077 if (domInsert) { 078 // NOTE (issue #477): DO NOT call DOM.insertChild() to correctly handle 079 // text nodes insertion according to the logical child widgets order. 080 // Calling DOM.insertChild(container, TEXT_NODE, beforeIndex) will 081 // always append the text node at the last position. 082 //DOM.insertChild(container, child.getElement(), beforeIndex); 083 Widget beforeWidget = getChildren().size() > beforeIndex + 1 ? 084 getChildren().get(beforeIndex + 1) : null; 085 if (beforeWidget == null) { 086 // Append to last position 087 DOM.appendChild(container, child.getElement()); 088 } else { 089 // Insert before the node of beforeWidget 090 container.insertBefore(child.getElement(), beforeWidget.getElement()); 091 } 092 } else { 093 DOM.appendChild(container, child.getElement()); 094 } 095 096 // Adopt. 097 adopt(child); 098 } 099 100 /** 101 * <p><b> 102 * Overrides the remove(Widget) method to avoid potential NPE when 103 * removing a {@link Text} node which is not supposed to be a 104 * "widget" in GWT. 105 * </b></p> 106 * {@inheritDoc} 107 */ 108 @Override 109 public boolean remove(Widget w) { 110 // Validate. 111 if (w.getParent() != this) { 112 return false; 113 } 114 // Orphan. 115 try { 116 orphan(w); 117 } finally { 118 // Physical detach. 119 Element elem = w.getElement(); 120 // NOTE (issue #486): DO NOT call DOM.getParent() to correctly handle 121 // text node removing. Calling DOM.getParent(TEXT_NODE) will throw a 122 // NPE exception. 123 //DOM.getParent(elem).removeChild(elem); 124 elem.removeFromParent(); 125 126 // Logical detach. 127 getChildren().remove(w); 128 } 129 return true; 130 } 131 132 /** 133 * {@inheritDoc} 134 */ 135 @Override 136 public void setId(final String id) { 137 idMixin.setId(id); 138 } 139 140 /** 141 * {@inheritDoc} 142 */ 143 @Override 144 public String getId() { 145 return idMixin.getId(); 146 } 147 148 /** 149 * {@inheritDoc} 150 */ 151 @Override 152 public void setVisibleOn(final DeviceSize deviceSize) { 153 StyleHelper.setVisibleOn(this, deviceSize); 154 } 155 156 /** 157 * {@inheritDoc} 158 */ 159 @Override 160 public void setHiddenOn(final DeviceSize deviceSize) { 161 StyleHelper.setHiddenOn(this, deviceSize); 162 } 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public void setMarginTop(final double margin) { 169 getElement().getStyle().setMarginTop(margin, Style.Unit.PX); 170 } 171 172 /** 173 * {@inheritDoc} 174 */ 175 @Override 176 public void setMarginLeft(final double margin) { 177 getElement().getStyle().setMarginLeft(margin, Style.Unit.PX); 178 } 179 180 /** 181 * {@inheritDoc} 182 */ 183 @Override 184 public void setMarginRight(final double margin) { 185 getElement().getStyle().setMarginRight(margin, Style.Unit.PX); 186 } 187 188 /** 189 * {@inheritDoc} 190 */ 191 @Override 192 public void setMarginBottom(final double margin) { 193 getElement().getStyle().setMarginBottom(margin, Style.Unit.PX); 194 } 195 196 /** 197 * {@inheritDoc} 198 */ 199 @Override 200 public void setPaddingTop(final double padding) { 201 getElement().getStyle().setPaddingTop(padding, Style.Unit.PX); 202 } 203 204 /** 205 * {@inheritDoc} 206 */ 207 @Override 208 public void setPaddingLeft(final double padding) { 209 getElement().getStyle().setPaddingLeft(padding, Style.Unit.PX); 210 } 211 212 /** 213 * {@inheritDoc} 214 */ 215 @Override 216 public void setPaddingRight(final double padding) { 217 getElement().getStyle().setPaddingRight(padding, Style.Unit.PX); 218 } 219 220 /** 221 * {@inheritDoc} 222 */ 223 @Override 224 public void setPaddingBottom(final double padding) { 225 getElement().getStyle().setPaddingBottom(padding, Style.Unit.PX); 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public void setColor(String color) { 233 getElement().getStyle().setColor(color); 234 } 235 236 /** 237 * {@inheritDoc} 238 */ 239 @Override 240 public void setPull(final Pull pull) { 241 pullMixin.setPull(pull); 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override 248 public Pull getPull() { 249 return pullMixin.getPull(); 250 } 251}