001/* 002 * #%L 003 * GwtMaterial 004 * %% 005 * Copyright (C) 2015 - 2017 GwtMaterialDesign 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package gwt.material.design.client.ui; 021 022import com.google.gwt.dom.client.Document; 023import com.google.gwt.dom.client.Element; 024import com.google.gwt.dom.client.Style; 025import com.google.gwt.event.shared.HandlerRegistration; 026import com.google.gwt.user.client.ui.HasValue; 027import com.google.gwt.user.client.ui.Widget; 028import gwt.material.design.client.base.*; 029import gwt.material.design.client.base.helper.UiHelper; 030import gwt.material.design.client.base.mixin.ActiveMixin; 031import gwt.material.design.client.base.mixin.CssTypeMixin; 032import gwt.material.design.client.base.mixin.ToggleStyleMixin; 033import gwt.material.design.client.constants.CollectionType; 034import gwt.material.design.client.constants.CssName; 035import gwt.material.design.client.js.JsMaterialElement; 036 037//@formatter:off 038 039/** 040 * Collection element to define every items 041 * 042 * @author kevzlou7979 043 * @author Ben Dol 044 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#collections">Material Collections</a> 045 * @see <a href="https://material.io/guidelines/components/lists-controls.html#lists-controls-types-of-menu-controls">Material Design Specification</a> 046 */ 047//@formatter:on 048public class MaterialCollectionItem extends MaterialWidget implements HasDismissible, HasAvatar, HasType<CollectionType>, HasActive { 049 050 private ToggleStyleMixin<MaterialCollectionItem> avatarMixin; 051 private ToggleStyleMixin<MaterialCollectionItem> dismissableMixin; 052 private CssTypeMixin<CollectionType, MaterialCollectionItem> typeMixin; 053 private ActiveMixin<MaterialCollectionItem> activeMixin; 054 055 public MaterialCollectionItem() { 056 super(Document.get().createLIElement(), CssName.COLLECTION_ITEM); 057 UiHelper.addMousePressedHandlers(this); 058 } 059 060 @Override 061 protected void onLoad() { 062 super.onLoad(); 063 064 HandlerRegistration handlerRegistration = addClickHandler(event -> { 065 // Stop propagation of event when checkbox / other elements has 066 // been clicked to avoid duplicate events. 067 if (Element.as(event.getNativeEvent().getEventTarget()) != getElement()) { 068 if (getType() == CollectionType.CHECKBOX) { 069 event.stopPropagation(); 070 event.preventDefault(); 071 } 072 } 073 for (Widget w : MaterialCollectionItem.this) { 074 if (w instanceof MaterialCollectionSecondary) { 075 for (Widget a : (MaterialCollectionSecondary) w) { 076 if (a instanceof HasValue) { 077 try { 078 @SuppressWarnings("unchecked") 079 HasValue<Boolean> cb = (HasValue<Boolean>) a; 080 if (cb.getValue()) { 081 cb.setValue(false); 082 } else { 083 cb.setValue(true); 084 } 085 } catch (ClassCastException ex) { 086 // Ignore non-boolean has value handlers. 087 } 088 } 089 } 090 } 091 } 092 }); 093 registerHandler(handlerRegistration); 094 095 JsMaterialElement.initDismissableCollection(); 096 } 097 098 @Override 099 public void setType(CollectionType type) { 100 getTypeMixin().setType(type); 101 if (type == CollectionType.CHECKBOX) { 102 applyCheckBoxType(); 103 } 104 } 105 106 protected void applyCheckBoxType() { 107 if (getWidgetCount() > 0) { 108 getWidget(0).getElement().getStyle().setDisplay(Style.Display.INLINE); 109 } 110 } 111 112 @Override 113 public CollectionType getType() { 114 return getTypeMixin().getType(); 115 } 116 117 @Override 118 public void setDismissible(boolean dismissible) { 119 getDismissableMixin().setOn(dismissible); 120 } 121 122 @Override 123 public boolean isDismissible() { 124 return getDismissableMixin().isOn(); 125 } 126 127 @Override 128 public void setAvatar(boolean avatar) { 129 getAvatarMixin().setOn(avatar); 130 } 131 132 @Override 133 public boolean isAvatar() { 134 return getAvatarMixin().isOn(); 135 } 136 137 @Override 138 public void setActive(boolean active) { 139 getActiveMixin().setActive(active); 140 } 141 142 @Override 143 public boolean isActive() { 144 return getActiveMixin().isActive(); 145 } 146 147 protected CssTypeMixin<CollectionType, MaterialCollectionItem> getTypeMixin() { 148 if (typeMixin == null) { 149 typeMixin = new CssTypeMixin<>(this); 150 } 151 return typeMixin; 152 } 153 154 protected ToggleStyleMixin<MaterialCollectionItem> getDismissableMixin() { 155 if (dismissableMixin == null) { 156 dismissableMixin = new ToggleStyleMixin<>(this, CssName.DISMISSABLE); 157 } 158 return dismissableMixin; 159 } 160 161 protected ToggleStyleMixin<MaterialCollectionItem> getAvatarMixin() { 162 if (avatarMixin == null) { 163 avatarMixin = new ToggleStyleMixin<>(this, CssName.AVATAR); 164 } 165 return avatarMixin; 166 } 167 168 protected ActiveMixin<MaterialCollectionItem> getActiveMixin() { 169 if (activeMixin == null) { 170 activeMixin = new ActiveMixin<>(this); 171 } 172 return activeMixin; 173 } 174}