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.base.viewport; 021 022import com.google.gwt.event.shared.HandlerRegistration; 023import gwt.material.design.client.js.Window; 024import gwt.material.design.jquery.client.api.Functions; 025 026import java.util.ArrayList; 027import java.util.Collections; 028import java.util.List; 029 030import static gwt.material.design.client.base.MaterialWidget.window; 031 032/** 033 * @author Ben Dol 034 */ 035public class ViewPortHandler { 036 037 private ViewPort viewPort; 038 039 private HandlerRegistration resize; 040 private List<Boundary> boundaries; 041 042 private Functions.Func1<ViewPortChange> then; 043 private ViewPortFallback fallback; 044 045 private boolean propagateFallback; 046 047 public ViewPortHandler(ViewPort viewPort, Boundary boundary, Boundary... other) { 048 this.viewPort = viewPort; 049 050 boundaries = new ArrayList<>(); 051 boundaries.add(boundary); 052 if(other != null) { 053 Collections.addAll(boundaries, other); 054 } 055 } 056 057 /** 058 * Apply more {@link Boundary}s to the detection conditions. 059 */ 060 public ViewPortHandler or(Boundary boundary) { 061 if(!boundaries.contains(boundary)) { 062 boundaries.add(boundary); 063 } 064 return this; 065 } 066 067 /** 068 * Load the view port execution. 069 * 070 * @param then callback when the view port is detected. 071 */ 072 public ViewPort then(Functions.Func1<ViewPortChange> then) { 073 return then(then, fallback); 074 } 075 076 /** 077 * Load the view port execution. 078 * 079 * @param then callback when the view port is detected. 080 * @param fallback fallback when no view port detected or failure to detect the given 081 * {@link Boundary} (using {@link #propagateFallback(boolean)}) 082 */ 083 public ViewPort then(Functions.Func1<ViewPortChange> then, ViewPortFallback fallback) { 084 assert then != null : "'then' callback cannot be null"; 085 this.then = then; 086 this.fallback = fallback; 087 return load(); 088 } 089 090 /** 091 * Destroy the {@link ViewPortHandler}. 092 */ 093 protected ViewPortHandler destroy() { 094 unload(); 095 boundaries.clear(); 096 then = null; 097 fallback = null; 098 return this; 099 } 100 101 protected ViewPortHandler unload() { 102 if(resize != null) { 103 resize.removeHandler(); 104 resize = null; 105 } 106 return this; 107 } 108 109 /** 110 * Load the windows resize handler with initial view port detection. 111 */ 112 protected ViewPort load() { 113 resize = Window.addResizeHandler(event -> { 114 execute(event.getWidth(), event.getHeight()); 115 }); 116 117 execute(window().width(), (int)window().height()); 118 return viewPort; 119 } 120 121 protected void execute(int width, int height) { 122 boolean match = false; 123 for(Boundary boundary : boundaries) { 124 if (Window.matchMedia(boundary.asMediaQuery())) { 125 then.call(new ViewPortChange(width, height, boundary)); 126 match = true; 127 } else if(propagateFallback && fallback != null && !fallback.call(new ViewPortRect(width, height))) { 128 // We will not propagate. 129 break; 130 } 131 } 132 133 if(!propagateFallback && !match && fallback != null) { 134 fallback.call(new ViewPortRect(width, height)); 135 } 136 137 } 138 139 public ViewPort getViewPort() { 140 return viewPort; 141 } 142 143 /** 144 * Execute fallback on each failure to detect view port. 145 */ 146 public void propagateFallback(boolean propagateFallback) { 147 this.propagateFallback = propagateFallback; 148 } 149}