001package com.github.gwtbootstrap.client.ui; 002 003import com.github.gwtbootstrap.client.ui.base.HasVisibility; 004import com.github.gwtbootstrap.client.ui.base.HasVisibleHandlers; 005import com.github.gwtbootstrap.client.ui.base.MarkupWidget; 006import com.github.gwtbootstrap.client.ui.constants.Constants; 007import com.github.gwtbootstrap.client.ui.constants.VisibilityChange; 008import com.github.gwtbootstrap.client.ui.event.HiddenEvent; 009import com.github.gwtbootstrap.client.ui.event.HiddenHandler; 010import com.github.gwtbootstrap.client.ui.event.HideEvent; 011import com.github.gwtbootstrap.client.ui.event.HideHandler; 012import com.github.gwtbootstrap.client.ui.event.ShowEvent; 013import com.github.gwtbootstrap.client.ui.event.ShowHandler; 014import com.github.gwtbootstrap.client.ui.event.ShownEvent; 015import com.github.gwtbootstrap.client.ui.event.ShownHandler; 016import com.google.gwt.core.client.Scheduler; 017import com.google.gwt.core.client.Scheduler.ScheduledCommand; 018import com.google.gwt.dom.client.Element; 019import com.google.gwt.event.shared.HandlerRegistration; 020import com.google.gwt.user.client.Event; 021import com.google.gwt.user.client.ui.Widget; 022 023/** 024 * Markup widget of Collapse 025 * <p> 026 * It's a markup widget (decorator widget). 027 * it's can exchange child to Collapsible widget. 028 * 029 * It's need trigger, You have 2 ways to create trigger.<br/> 030 * <ol> 031 * <li> Using {@link CollapseTrigger}. </li> 032 * <li> Calling {@link #toggle()}. </li> 033 * </ol> 034 * </p> 035 * 036 * <p> 037 * <h3>UiBinder Usage:</h3> 038 * </p> 039 * <pre> 040 * {@code 041 * <b:Collapse b:id="toggle1" defaultOpen="true"> 042 * <!-- it can be added any widget, but accept one wdiget. 043 * <b:Label>aaa</b:Label> 044 * </b:Collapse> 045 * } 046 * </pre> 047 * 048 * @since 2.2.1.0 049 * @author ohashi keisuke 050 * @see Accordion 051 * @see Collapse 052 * @see CollapseTrigger 053 * @see <a href="http://twitter.github.com/bootstrap/javascript.html#collapse">Twitter Bootstrap document</a> 054 * 055 * 056 */ 057public class Collapse extends MarkupWidget implements HasVisibility, HasVisibleHandlers { 058 059 private String parent; 060 061 private boolean toggle = false; 062 063 private boolean existTrigger = false; 064 065 private boolean dafaultOpen; 066 067 /** 068 * Get parent selector 069 * @return parent parent selector 070 */ 071 public String getParent() { 072 return parent; 073 } 074 075 /** 076 * Set parent selector. 077 * 078 * it only work with {@link AccordionGroup}, 079 * Please see <a href="https://github.com/twitter/bootstrap/issues/4988">this issue</a>. 080 * 081 * @param parent parent selector 082 */ 083 public void setParent(String parent) { 084 this.parent = parent; 085 } 086 087 /** 088 * is the collapsible element toggled on invocation 089 * @return toggle true:toggled , false: un-toggled 090 */ 091 public boolean isToggle() { 092 return toggle; 093 } 094 095 /** 096 * Toggles the collapsible element on invocation 097 * @param toggle true: toggled on invocation , false : not-toggled 098 */ 099 public void setToggle(boolean toggle) { 100 this.toggle = toggle; 101 } 102 103 public void setDefaultOpen(boolean dafaultOpen) { 104 this.dafaultOpen = dafaultOpen; 105 106 if(widget != null && !widget.isAttached()) { 107 widget.setStyleName(Constants.IN , dafaultOpen); 108 } 109 110 } 111 112 /** 113 * {@inheritDoc} 114 */ 115 @Override 116 public Widget asWidget() { 117 118 if(widget != null) { 119 Scheduler.get().scheduleDeferred(new ScheduledCommand() { 120 121 @Override 122 public void execute() { 123 if(!isExistTrigger()){ 124 reconfigure(); 125 } else { 126 setHandlerFunctions(widget.getElement()); 127 } 128 } 129 }); 130 } 131 132 return getWidget(); 133 } 134 135 /** 136 * {@inheritDoc} 137 */ 138 @Override 139 public void setWidget(Widget w) { 140 super.setWidget(w); 141 142 if(widget != null) { 143 widget.addStyleName(Constants.COLLAPSE); 144 } 145 146 } 147 148 /** 149 * {@inheritDoc} 150 */ 151 @Override 152 public HandlerRegistration addHideHandler(HideHandler handler) { 153 return getWidget().addHandler(handler, HideEvent.getType()); 154 } 155 156 /** 157 * {@inheritDoc} 158 */ 159 @Override 160 public HandlerRegistration addHiddenHandler(HiddenHandler handler) { 161 return getWidget().addHandler(handler, HiddenEvent.getType()); 162 } 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public HandlerRegistration addShowHandler(ShowHandler handler) { 169 return getWidget().addHandler(handler, ShowEvent.getType()); 170 } 171 172 /** 173 * {@inheritDoc} 174 */ 175 @Override 176 public HandlerRegistration addShownHandler(ShownHandler handler) { 177 return getWidget().addHandler(handler, ShownEvent.getType()); 178 } 179 180 /** 181 * {@inheritDoc} 182 */ 183 @Override 184 public void show() { 185 changeVisibility(VisibilityChange.SHOW); 186 } 187 188 /** 189 * {@inheritDoc} 190 */ 191 @Override 192 public void hide() { 193 changeVisibility(VisibilityChange.HIDE); 194 } 195 196 /** 197 * {@inheritDoc} 198 */ 199 @Override 200 public void toggle() { 201 changeVisibility(VisibilityChange.TOGGLE); 202 } 203 204 /** 205 * Change visibility 206 * @param visibilityChange call method 207 */ 208 protected void changeVisibility(VisibilityChange visibilityChange) { 209 210 if(widget == null) return; 211 212 changeVisibility(widget.getElement() , visibilityChange.get()); 213 } 214 215 /** 216 * Is exist Trigger? 217 * @return existTrigger 218 */ 219 public boolean isExistTrigger() { 220 return existTrigger; 221 } 222 223 /** 224 * Is there the trigger(Collapse Trigger) 225 * @param existTrigger exists:true, none:false 226 */ 227 public void setExistTrigger(boolean existTrigger) { 228 this.existTrigger = existTrigger; 229 } 230 231 /** 232 * re configure setting 233 */ 234 public void reconfigure() { 235 236 if(widget == null) return; 237 238 setDefaultOpen(dafaultOpen); 239 240 removeDataIfExists(widget.getElement()); 241 242 setHandlerFunctions(widget.getElement()); 243 244 configure(widget.getElement(), parent, toggle); 245 } 246 247 //@fomatter:off 248 /** 249 * Configure collapse settings. 250 * @param e element 251 * @param parent parent selector 252 * @param toggle is toggled on added document 253 */ 254 public native void configure(Element e, String parent, boolean toggle) /*-{ 255 $wnd.jQuery(e).collapse({ 256 "parent" : parent || false, 257 "toggle" : toggle 258 }); 259 }-*/; 260 261 /** 262 * Configure collapse settings. 263 * @param selector selector 264 * @param parent parent selector 265 * @param toggle is toggled on added document 266 */ 267 public static native void configure(String selector, String parent, boolean toggle) /*-{ 268 $wnd.jQuery(selector).collapse({ 269 "parent" : parent || false, 270 "toggle" : toggle 271 }); 272 273 }-*/; 274 275 /** 276 * Remove data api. 277 * @param e element 278 */ 279 protected native void removeDataIfExists(Element e) /*-{ 280 var $this = $wnd.jQuery(e); 281 if($this.data('collapse')) { 282 $this.removeData('parent').removeData('toggle').removeData('collapse'); 283 } 284 }-*/; 285 286 /** 287 * Links the Java functions that fire the events. 288 */ 289 protected native void setHandlerFunctions(Element e) /*-{ 290 var that = this; 291 var $this = $wnd.jQuery(e); 292 293 $this.off('show'); 294 $this.off('shown'); 295 $this.off('hide'); 296 $this.off('hidden'); 297 298 $this.on('hide', function(e) { 299 [email protected]::onHide(Lcom/google/gwt/user/client/Event;)(e); 300 }); 301 $this.on('hidden', function(e) { 302 [email protected]::onHidden(Lcom/google/gwt/user/client/Event;)(e); 303 }); 304 $this.on('show', function(e) { 305 [email protected]::onShow(Lcom/google/gwt/user/client/Event;)(e); 306 }); 307 $this.on('shown', function(e) { 308 [email protected]::onShown(Lcom/google/gwt/user/client/Event;)(e); 309 }); 310 }-*/; 311 312 protected native void changeVisibility(Element e , String c) /*-{ 313 $wnd.jQuery(e).collapse(c); 314 }-*/; 315 316 public static native void changeVisibility(String target , String c) /*-{ 317 $wnd.jQuery(target).collapse(c); 318 }-*/; 319 //@fomatter:on 320 321 322 /** 323 * This method is called immediately when the widget's {@link #hide()} 324 * method is executed. 325 */ 326 protected void onHide(Event e) { 327 widget.fireEvent(new HideEvent(e)); 328 } 329 330 /** 331 * This method is called once the widget is completely hidden. 332 */ 333 protected void onHidden(Event e) { 334 widget.fireEvent(new HiddenEvent(e)); 335 } 336 337 /** 338 * This method is called immediately when the widget's {@link #show()} 339 * method is executed. 340 */ 341 protected void onShow(Event e) { 342 widget.fireEvent(new ShowEvent(e)); 343 } 344 345 /** 346 * This method is called once the widget is completely shown. 347 */ 348 protected void onShown(Event e) { 349 widget.fireEvent(new ShownEvent(e)); 350 } 351}