• R/O
  • SSH
  • HTTPS

merlin: コミット


コミットメタ情報

リビジョン4 (tree)
日時2016-09-29 17:33:36
作者hirukawa_ryo

ログメッセージ

(メッセージはありません)

変更サマリ

差分

--- Merlin/app/src/main/java/demo/Box.java (nonexistent)
+++ Merlin/app/src/main/java/demo/Box.java (revision 4)
@@ -0,0 +1,28 @@
1+package demo;
2+
3+import android.graphics.Canvas;
4+import android.graphics.Paint;
5+
6+import net.osdn.merlin.core.ui.Attributes;
7+import net.osdn.merlin.core.ui.Component;
8+
9+public class Box extends Component {
10+
11+ private Paint paint;
12+
13+ public Box(String name, Attributes.Holder attributes, int color) {
14+ super(name, attributes);
15+ paint = new Paint();
16+ paint.setColor(color);
17+ paint.setStyle(Paint.Style.FILL);
18+
19+ setElevation(20);
20+ }
21+
22+ @Override
23+ protected void onDraw(Canvas canvas) {
24+ canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
25+ }
26+
27+
28+}
--- Merlin/app/src/main/java/demo/MainActivity.java (revision 3)
+++ Merlin/app/src/main/java/demo/MainActivity.java (revision 4)
@@ -10,7 +10,6 @@
1010 import android.util.Log;
1111 import android.view.Gravity;
1212 import android.view.ViewGroup;
13-import android.view.Window;
1413 import android.view.WindowManager;
1514 import android.widget.Toast;
1615
@@ -17,13 +16,14 @@
1716 import net.osdn.merlin.R;
1817 import net.osdn.merlin.core.ApplicationActivity;
1918 import net.osdn.merlin.core.Event;
19+import net.osdn.merlin.core.ui.Attributes;
2020 import net.osdn.merlin.core.ui.Component;
21+import net.osdn.merlin.core.ui.Window;
2122
2223 public class MainActivity extends ApplicationActivity {
2324
24- @Override
25- public void main() {
26-
25+ /* SHADOW TEST */
26+ private void testShadow() {
2727 TestComponent c0 = new TestComponent("tc0", null, 0, 0, 600, 800, Color.argb(127, 0, 255, 0));
2828 c0.setMinimumSize(600, 600);
2929 c0.setSoundEffectsEnabled(false);
@@ -38,30 +38,30 @@
3838 c3.setMinimumSize(300, 200);
3939
4040 WindowManager.LayoutParams params0 = new WindowManager.LayoutParams(
41- WindowManager.LayoutParams.MATCH_PARENT,
42- WindowManager.LayoutParams.MATCH_PARENT,
43- WindowManager.LayoutParams.TYPE_TOAST,
44- WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
45- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
41+ WindowManager.LayoutParams.MATCH_PARENT,
42+ WindowManager.LayoutParams.MATCH_PARENT,
43+ WindowManager.LayoutParams.TYPE_TOAST,
44+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
45+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
4646 // | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
4747 // | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
48- ,
49- PixelFormat.TRANSLUCENT);
48+ ,
49+ PixelFormat.TRANSLUCENT);
5050
5151 WindowManager.LayoutParams params1 = new WindowManager.LayoutParams(
52- WindowManager.LayoutParams.MATCH_PARENT,
53- WindowManager.LayoutParams.MATCH_PARENT,
54- WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
55- WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
56- PixelFormat.TRANSLUCENT);
52+ WindowManager.LayoutParams.MATCH_PARENT,
53+ WindowManager.LayoutParams.MATCH_PARENT,
54+ WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
55+ WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
56+ PixelFormat.TRANSLUCENT);
5757 params1.token = null;
5858
5959 WindowManager.LayoutParams params2 = new WindowManager.LayoutParams(
60- WindowManager.LayoutParams.MATCH_PARENT,
61- WindowManager.LayoutParams.MATCH_PARENT,
62- WindowManager.LayoutParams.TYPE_APPLICATION,
63- WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
64- PixelFormat.TRANSLUCENT);
60+ WindowManager.LayoutParams.MATCH_PARENT,
61+ WindowManager.LayoutParams.MATCH_PARENT,
62+ WindowManager.LayoutParams.TYPE_APPLICATION,
63+ WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
64+ PixelFormat.TRANSLUCENT);
6565 params2.token = null;
6666
6767 WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
@@ -107,7 +107,7 @@
107107
108108 Dialog d2 = new Dialog(getContext());
109109 d2.getWindow().getAttributes().token = getWindow().getAttributes().token;
110- d2.requestWindowFeature(Window.FEATURE_NO_TITLE);
110+ //d2.requestWindowFeature(Window.FEATURE_NO_TITLE);
111111 d2.setCanceledOnTouchOutside(true);
112112 d2.getWindow().getAttributes().gravity = Gravity.LEFT | Gravity.TOP;
113113 d2.getWindow().getAttributes().x = 100;
@@ -117,9 +117,15 @@
117117 //d2.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
118118 d2.show();
119119 Log.d("MainActivity", "type2=" + d2.getWindow().getAttributes().type);
120+ }
120121
122+ @Override
123+ public void main() {
124+ //transitTo(State1.class);
121125
126+ Box box1 = new Box("box1", Attributes.location(50, 50).size(100, 100), Color.WHITE);
127+ Window window = new Window(box1);
122128
123- run(State1.class);
129+ setContentView(window.getView(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
124130 }
125131 }
--- Merlin/app/src/main/java/demo/State1.java (revision 3)
+++ Merlin/app/src/main/java/demo/State1.java (revision 4)
@@ -1,6 +1,37 @@
11 package demo;
22
3+import android.graphics.Color;
4+import android.util.Log;
5+
36 import net.osdn.merlin.core.State;
7+import net.osdn.merlin.core.ui.Component;
8+import net.osdn.merlin.core.ui.event.ClickEvent;
49
510 public class State1 extends State {
11+ private static final String TAG = "State1";
12+
13+ @Override
14+ protected Component createContent() {
15+ return new TestComponent("tc", null, 100, 100, 200, 200, Color.RED);
16+ }
17+
18+ @Override
19+ protected void onInitialize(boolean isFirstTime) throws Exception {
20+ Log.d(TAG, "onInitialize: isFirstTime=" + isFirstTime);
21+ }
22+
23+ @Override
24+ protected void onEntry(State previousState) throws Exception {
25+ Log.d(TAG, "onEntry: previousState=" + previousState);
26+ Log.d(TAG, "onEntry: thread=" + Thread.currentThread().getName());
27+ }
28+
29+ @Override
30+ protected void onExit(State nextState) throws Exception {
31+ Log.d(TAG, "onExit: nextState=" + nextState);
32+ }
33+
34+ protected void t(ClickEvent e) throws Exception {
35+ Log.d(TAG, "tc(ClickEvent e);");
36+ }
637 }
--- Merlin/app/src/main/java/demo/TestComponent.java (revision 3)
+++ Merlin/app/src/main/java/demo/TestComponent.java (revision 4)
@@ -8,8 +8,10 @@
88 import android.widget.Toast;
99
1010 import net.osdn.merlin.core.ApplicationActivity;
11+import net.osdn.merlin.core.EventDispatcher;
1112 import net.osdn.merlin.core.ui.Attributes;
1213 import net.osdn.merlin.core.ui.Component;
14+import net.osdn.merlin.core.ui.event.ClickEvent;
1315
1416 public class TestComponent extends Component {
1517 private static final String TAG = "TestComponent";
@@ -32,6 +34,7 @@
3234 public void onClick(View v) {
3335 Log.d("TextComponent", getName() + ": click");
3436 Toast.makeText(ApplicationActivity.getContext(), "HELLO: " + getName(), Toast.LENGTH_LONG);
37+ EventDispatcher.post(new ClickEvent(TestComponent.this));
3538 }
3639 });
3740 }
--- Merlin/library/src/main/java/net/osdn/merlin/core/ComponentEvent.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ComponentEvent.java (nonexistent)
@@ -1,4 +0,0 @@
1-package net.osdn.merlin.core;
2-
3-public class ComponentEvent implements Event {
4-}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ApplicationActivity.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ApplicationActivity.java (revision 4)
@@ -5,7 +5,11 @@
55 import android.content.res.Configuration;
66 import android.os.Bundle;
77 import android.util.Log;
8+import android.view.ViewGroup;
89
10+import net.osdn.merlin.core.event.EntryEvent;
11+import net.osdn.merlin.core.ui.Component;
12+
913 public abstract class ApplicationActivity extends Activity {
1014 private static final String TAG = "ApplicationActivity";
1115 public static boolean DEBUG = true;
@@ -153,28 +157,29 @@
153157 super.onConfigurationChanged(newConfig);
154158 }
155159
156- protected void transitTo(Class<? extends State> stateClass) {
160+ protected void transitTo(Class<? extends State> stateClass, Object... arguments) {
157161 State state = StateManager.getInstance(stateClass);
158- transitTo(state);
162+ transitTo(state, arguments);
159163 }
160164
161- protected void transitTo(State state) {
165+ protected void transitTo(State firstState, Object... arguments) {
162166 if(DEBUG) {
163- Log.d(TAG, "run: state=" + state);
167+ Log.d(TAG, "transitTo: firstState=" + firstState);
164168 }
165169
166- if(state == null) {
170+ if(firstState == null) {
167171
168172 }
169173
170- state.setContext(context);
171174
175+ firstState.setContext(context);
176+ Component content = firstState.getContent();
177+ setContentView(content.getView(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
178+
179+ StateManager.push(firstState);
172180 EventDispatcher dispatcher = new EventDispatcher();
173- Log.d(TAG, "#1");
174181 dispatcher.start();
175- Log.d(TAG, "#2");
176- dispatcher.post(new ComponentEvent());
177- Log.d(TAG, "#3");
182+ EventDispatcher.post(new EntryEvent(firstState, null));
178183 }
179184
180185 public static Context getContext() {
--- Merlin/library/src/main/java/net/osdn/merlin/core/Event.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/Event.java (revision 4)
@@ -1,4 +1,16 @@
11 package net.osdn.merlin.core;
22
3+import java.lang.reflect.Method;
4+
35 public interface Event {
6+
7+ State getState();
8+
9+ Object getSource();
10+
11+ Method getHandler();
12+
13+ Object getHandlerArguments();
14+
15+ Exception getException();
416 }
--- Merlin/library/src/main/java/net/osdn/merlin/core/EventDispatcher.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/EventDispatcher.java (revision 4)
@@ -2,6 +2,7 @@
22
33 import android.util.Log;
44
5+import java.lang.reflect.InvocationTargetException;
56 import java.util.LinkedList;
67 import java.util.concurrent.BlockingQueue;
78 import java.util.concurrent.ExecutorService;
@@ -30,22 +31,46 @@
3031 stack = new LinkedList<EventDispatcher>();
3132 }
3233
33-
34+ private boolean isRunning;
35+ private Thread thread;
3436 private BlockingQueue<Event> queue = new LinkedBlockingQueue<Event>();
37+ private State state;
3538
3639 protected EventDispatcher() {
37- Log.d(TAG, ".ctor");
40+ if(DEBUG) {
41+ Log.d(TAG, ".ctor");
42+ }
43+
3844 stack.add(this);
3945 }
4046
4147 protected void start() {
42- Log.d(TAG, "start");
48+ if(DEBUG) {
49+ Log.d(TAG, "start");
50+ }
51+
4352 threadPool.submit(this);
4453 }
4554
55+ protected void stop() {
56+ if(DEBUG) {
57+ Log.d(TAG, "stop");
58+ }
59+
60+ isRunning = false;
61+ if(thread != null) {
62+ thread.interrupt();
63+ }
64+ }
65+
4666 public void run() {
47- Log.d(TAG, "run");
48- while(true) {
67+ if(DEBUG) {
68+ Log.d(TAG, "run");
69+ }
70+
71+ thread = Thread.currentThread();
72+ isRunning = true;
73+ while(isRunning) {
4974 try {
5075 Log.d(TAG, "[S] queue.take();");
5176 Event event = this.queue.take();
@@ -54,14 +79,9 @@
5479 } catch (InterruptedException e) {
5580 }
5681 }
82+ thread = null;
5783 }
5884
59- protected void dispatch(Event event) {
60- if(DEBUG) {
61- Log.d(TAG, "dispatch: event=" + event);
62- }
63- }
64-
6585 public static void post(Event event) {
6686 if(DEBUG) {
6787 Log.d(TAG, "post: event=" + event);
@@ -71,6 +91,26 @@
7191 dispatcher.queue.offer(event);
7292 }
7393
94+ protected void dispatch(Event event) {
95+ if(DEBUG) {
96+ Log.d(TAG, "dispatch: event=" + event);
97+ }
98+
99+ Exception exception = event.getException();
100+ if(exception instanceof NoSuchMethodException) {
101+ Log.w(TAG, exception.getMessage());
102+ return;
103+ }
104+
105+ try {
106+ event.getHandler().invoke(event.getState(), event.getHandlerArguments());
107+ } catch (IllegalAccessException e) {
108+ throw new FrameworkException(e);
109+ } catch (InvocationTargetException e) {
110+ throw new FrameworkException(e);
111+ }
112+ }
113+
74114 private static class EventDispatcherThreadFactory implements ThreadFactory {
75115
76116 private AtomicInteger number = new AtomicInteger();
--- Merlin/library/src/main/java/net/osdn/merlin/core/ReflectionUtil.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ReflectionUtil.java (revision 4)
@@ -0,0 +1,208 @@
1+package net.osdn.merlin.core;
2+
3+import java.lang.reflect.Field;
4+import java.lang.reflect.Method;
5+import java.lang.reflect.Modifier;
6+import java.util.Arrays;
7+import java.util.HashMap;
8+import java.util.LinkedList;
9+import java.util.Map;
10+
11+public class ReflectionUtil {
12+
13+ private static final Map<Class<?>, Field[]> visibleFieldsCache = new HashMap<Class<?>, Field[]>();
14+ private static final Map<Key, Method> methodCache = new HashMap<Key, Method>();
15+ private static final Map<Key, Boolean> overrideCache = new HashMap<Key, Boolean>();
16+
17+ /** 指定したクラスの可視フィールドを返します。
18+ * 可視フィールドには指定したクラス自身のprivateフィールドも含まれますが、
19+ * 指定したクラスのスーパークラスのprivateフィールドは含まれません。
20+ * 返される可視フィールドはアクセス可能に設定されます。
21+ *
22+ * @param cls 可視フィールド取得対象のクラス
23+ * @return アクセス可能に設定された可視フィールド配列
24+ */
25+ public static Field[] getVisibleFields(Class<?> cls) {
26+ Field[] f = visibleFieldsCache.get(cls);
27+ if(f != null) {
28+ return f;
29+ }
30+
31+ Map<String, Field> map = new HashMap<String, Field>();
32+
33+ LinkedList<Class<?>> classes = new LinkedList<Class<?>>();
34+ Class<?> sc = cls;
35+ while((sc = sc.getSuperclass()) != null) {
36+ classes.addFirst(sc);
37+ }
38+ for(Class<?> c : classes) {
39+ for(Field field : c.getDeclaredFields()) {
40+ if(!Modifier.isPrivate(field.getModifiers())) {
41+ map.put(field.getName(), field);
42+ }
43+ }
44+ }
45+ for(Field field : cls.getDeclaredFields()) {
46+ map.put(field.getName(), field);
47+ }
48+ Field[] fields = map.values().toArray(new Field[] {});
49+ Field.setAccessible(fields, true);
50+ visibleFieldsCache.put(cls, fields);
51+ return fields;
52+ }
53+
54+
55+ /** 指定した内容に一致するインスタンスメソッドを返します。
56+ * 指定したクラスのスーパークラスに定義されているメソッドも対象になります。
57+ * 返されるメソッドはアクセス可能に設定されます。
58+ *
59+ * @param cls メソッド取得対象のクラス
60+ * @param name メソッド名
61+ * @param parameterTypes メソッドの引数の型
62+ * @return 見つかったメソッド
63+ * @throws NoSuchMethodException
64+ */
65+ public static Method getMethod(Class<?> cls, String name, Class<?>... parameterTypes) throws NoSuchMethodException {
66+ if(parameterTypes == null) {
67+ parameterTypes = new Class[] {};
68+ }
69+
70+ Key key = new Key(cls, name, parameterTypes);
71+ Method m = methodCache.get(key);
72+ if(m != null) {
73+ return m;
74+ }
75+
76+ Class<?> c = cls;
77+ while(c != null) {
78+ for(Method method : c.getDeclaredMethods()) {
79+ if(method.getName().equals(name) && method.getParameterTypes().length == parameterTypes.length) {
80+ if(Modifier.isStatic(method.getModifiers())) {
81+ continue;
82+ }
83+ boolean isParameterTypesMatched = true;
84+ for(int i = 0; i < parameterTypes.length; i++) {
85+ if(!parameterTypes[i].isAssignableFrom(method.getParameterTypes()[i])) {
86+ isParameterTypesMatched = false;
87+ }
88+ }
89+ if(isParameterTypesMatched) {
90+ method.setAccessible(true);
91+ methodCache.put(key, method);
92+ return method;
93+ }
94+ }
95+ }
96+ c = c.getSuperclass();
97+ }
98+ StringBuilder sb = new StringBuilder();
99+ sb.append(cls.getSimpleName());
100+ sb.append(".");
101+ sb.append(name);
102+ sb.append("(");
103+ if(parameterTypes.length > 0) {
104+ for(int i = 0; i < parameterTypes.length; i++) {
105+ sb.append(parameterTypes[i].getSimpleName());
106+ sb.append(", ");
107+ }
108+ sb.delete(sb.length() - 2, sb.length());
109+ }
110+ sb.append(")");
111+ throw new NoSuchMethodException(sb.toString());
112+ }
113+
114+ /** 対象クラス(targetClass)が、スーパークラス(superClass)の指定したメソッドをオーバーライドしているか調べます。
115+ * 対象クラス(targetClass)が、指定メソッドを直接オーバーライドしていなくても(superClassを継承した)親クラスのいずれかで
116+ * 指定メソッドがオーバーライドされている場合はtrueを返します。
117+ *
118+ * @param targetClass
119+ * @param superClass
120+ * @param methodName
121+ * @param parameterTypes
122+ * @return 対象クラスまたは親クラスのいずれかで指定メソッドをオーバーライドしている場合はtrue、そうでなければfalse。
123+ */
124+ public static boolean isMethodOverrided(Class<?> targetClass, Class<?> superClass, String methodName, Class<?>... parameterTypes) {
125+ if(parameterTypes == null) {
126+ parameterTypes = new Class[] {};
127+ }
128+
129+ Key key = new Key(targetClass, superClass, methodName, parameterTypes);
130+ Boolean b = overrideCache.get(key);
131+ if(b != null) {
132+ return b;
133+ }
134+
135+ Method method = null;
136+ Class<?> cls = targetClass;
137+ while(cls != null && method == null) {
138+ if(cls == superClass) {
139+ break;
140+ }
141+ try {
142+ method = cls.getDeclaredMethod(methodName, parameterTypes);
143+ } catch(SecurityException e) {
144+ e.printStackTrace();
145+ } catch(NoSuchMethodException e) {
146+ }
147+ cls = cls.getSuperclass();
148+ }
149+
150+ b = (method != null);
151+ overrideCache.put(key, b);
152+ return b;
153+ }
154+
155+ private static class Key {
156+
157+ Object[] elements;
158+
159+ public Key(Class<?> cls) {
160+ elements = new Object[] { cls };
161+ }
162+
163+ public Key(Class<?> cls, String name, Class<?>... parameterTypes) {
164+ elements = new Object[2 + parameterTypes.length];
165+ elements[0] = cls;
166+ elements[1] = name;
167+ for(int i = 0; i < parameterTypes.length; i++) {
168+ elements[2 + i] = parameterTypes[i];
169+ }
170+ }
171+
172+ public Key(Class<?> targetClass, Class<?> superClass, String methodName, Class<?>... parameterTypes) {
173+ elements = new Object[3 + parameterTypes.length];
174+ elements[0] = targetClass;
175+ elements[1] = superClass;
176+ elements[2] = methodName;
177+ for(int i = 0; i < parameterTypes.length; i++) {
178+ elements[3 + i] = parameterTypes[i];
179+ }
180+ }
181+
182+ @Override
183+ public int hashCode() {
184+ final int prime = 31;
185+ int result = 1;
186+ result = prime * result + Arrays.hashCode(elements);
187+ return result;
188+ }
189+
190+ @Override
191+ public boolean equals(Object obj) {
192+ if (this == obj) {
193+ return true;
194+ }
195+ if (obj == null) {
196+ return false;
197+ }
198+ if (getClass() != obj.getClass()) {
199+ return false;
200+ }
201+ Key other = (Key) obj;
202+ if (!Arrays.equals(elements, other.elements)) {
203+ return false;
204+ }
205+ return true;
206+ }
207+ }
208+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/State.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/State.java (revision 4)
@@ -2,9 +2,14 @@
22
33 import android.content.Context;
44
5-public class State {
5+import net.osdn.merlin.core.ui.Component;
66
7+public abstract class State {
8+
79 private Context context;
10+ private Component content;
11+ private Object[] arguments;
12+ private State previousState;
813
914 protected void setContext(Context context) {
1015 this.context = context;
@@ -13,4 +18,35 @@
1318 public Context getContext() {
1419 return this.context;
1520 }
21+
22+ public Component getContent() {
23+ if(content == null) {
24+ content = createContent();
25+ }
26+
27+ return content;
28+ }
29+
30+ protected abstract Component createContent();
31+
32+ protected abstract void onInitialize(boolean isFirstTime) throws Exception;
33+
34+ protected abstract void onEntry(State previousState) throws Exception;
35+
36+ protected abstract void onExit(State nextState) throws Exception;
37+
38+ protected <T> T transitTo(Class<? extends State> nextStateClass, Object... arguments) {
39+ return transitTo(StateManager.getInstance(nextStateClass), arguments);
40+ }
41+
42+ protected <T> T transitTo(State nextState, Object... arguments) {
43+ nextState.arguments = arguments;
44+ nextState.previousState = this;
45+
46+ //FOR SUB-STATE
47+
48+
49+ return null;
50+ }
51+
1652 }
--- Merlin/library/src/main/java/net/osdn/merlin/core/StateManager.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/StateManager.java (revision 4)
@@ -1,18 +1,30 @@
11 package net.osdn.merlin.core;
22
3+import android.content.Context;
4+import android.view.ViewGroup;
5+
6+import net.osdn.merlin.core.event.EntryEvent;
7+import net.osdn.merlin.core.ui.Component;
8+
39 import java.util.HashMap;
10+import java.util.LinkedList;
411 import java.util.Map;
512
613 public class StateManager {
714
815 private static Map<Class<? extends State>, State> instances;
16+ private static LinkedList<State> stack;
917
1018 protected static void initializeStaticFields() {
1119 if(instances != null) {
1220 instances.clear();
1321 }
22+ if(stack != null) {
23+ stack.clear();
24+ }
1425
1526 instances = new HashMap<Class<? extends State>, State>();
27+ stack = new LinkedList<State>();
1628 }
1729
1830
@@ -31,4 +43,15 @@
3143 return (T)state;
3244 }
3345
46+ /* package private */ static void push(State state) {
47+ stack.push(state);
48+ }
49+
50+ /* package private */ static State pop() {
51+ return stack.pop();
52+ }
53+
54+ public static State getCurrentState() {
55+ return stack.getLast();
56+ }
3457 }
--- Merlin/library/src/main/java/net/osdn/merlin/core/event/AbstractEvent.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/event/AbstractEvent.java (revision 4)
@@ -0,0 +1,18 @@
1+package net.osdn.merlin.core.event;
2+
3+import net.osdn.merlin.core.Event;
4+import net.osdn.merlin.core.State;
5+
6+import java.lang.reflect.Method;
7+
8+public abstract class AbstractEvent implements Event {
9+
10+ private State state;
11+ private Object source;
12+ private Method handler;
13+ private Object arguments;
14+
15+ protected AbstractEvent() {
16+
17+ }
18+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/event/EntryEvent.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/event/EntryEvent.java (revision 4)
@@ -0,0 +1,46 @@
1+package net.osdn.merlin.core.event;
2+
3+import net.osdn.merlin.core.Event;
4+import net.osdn.merlin.core.FrameworkException;
5+import net.osdn.merlin.core.ReflectionUtil;
6+import net.osdn.merlin.core.State;
7+
8+import java.lang.reflect.Method;
9+
10+public class EntryEvent implements Event {
11+
12+ private State nextState;
13+ private State previousState;
14+ private Method handler;
15+
16+ public EntryEvent(State nextState, State previousState) {
17+ this.nextState = nextState;
18+ this.previousState = previousState;
19+
20+ try {
21+ handler = ReflectionUtil.getMethod(nextState.getClass(), "onEntry", State.class);
22+ } catch (NoSuchMethodException e) {
23+ throw new FrameworkException(e);
24+ }
25+ }
26+
27+ public State getState() {
28+ return nextState;
29+ }
30+
31+ public State getSource() {
32+ return previousState;
33+ }
34+
35+ public Method getHandler() {
36+ return handler;
37+ }
38+
39+ public State getHandlerArguments() {
40+ return previousState;
41+ }
42+
43+ public Exception getException() {
44+ return null;
45+ }
46+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/event/ExitEvent.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/event/ExitEvent.java (revision 4)
@@ -0,0 +1,8 @@
1+package net.osdn.merlin.core.event;
2+
3+/**
4+ * Created by HIRUKAWA Ryo on 2016/09/28.
5+ */
6+
7+public class ExitEvent {
8+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/Component.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/Component.java (revision 4)
@@ -3,6 +3,7 @@
33 import android.annotation.SuppressLint;
44 import android.content.Context;
55 import android.graphics.Canvas;
6+import android.graphics.Path;
67 import android.graphics.Rect;
78 import android.graphics.drawable.Drawable;
89 import android.util.SparseArray;
@@ -19,6 +20,11 @@
1920
2021 public class Component {
2122
23+ public static final int GONE = View.GONE;
24+ public static final int VISIBLE = View.VISIBLE;
25+ public static final int INVISIBLE = View.INVISIBLE;
26+
27+
2228 private DelegateView delegate;
2329 private Container parent;
2430 private String name;
@@ -37,6 +43,8 @@
3743 private int x = -1; //for AbsoluteLayout
3844 private int y = -1; //for AbsoluteLayout
3945
46+ private int elevation;
47+ private Path shadowPath;
4048 private Object tag;
4149 private SparseArray<Object> tags;
4250
@@ -236,6 +244,30 @@
236244 return (View)getDelegate();
237245 }
238246
247+ public void setElevation(int elevation) {
248+ if(elevation >= 0) {
249+ this.elevation = elevation;
250+ } else {
251+ elevation = 0;
252+ }
253+ }
254+
255+ public int getElevation() {
256+ return this.elevation;
257+ }
258+
259+ public void setShadowPath(Path path) {
260+ this.shadowPath = path;
261+ }
262+
263+ public Path getShadowPath() {
264+ if(elevation >= 1 && shadowPath == null) {
265+ shadowPath = new Path();
266+ shadowPath.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW);
267+ }
268+ return this.shadowPath;
269+ }
270+
239271 /** このコンポーネントに関連したタグを設定します。
240272 * アプリケーションは任意のオブジェクトをタグとして設定・参照することができます。
241273 * フレームワークがタグを設定・参照することはありません。
@@ -1489,6 +1521,10 @@
14891521 return getDelegate()._dispatchTouchEvent(event);
14901522 }
14911523
1524+ protected void dispatchDraw(Canvas canvas) {
1525+ getDelegate()._dispatchDraw(canvas);
1526+ }
1527+
14921528 public void draw(Canvas canvas) {
14931529 if(UiThread.isUiThread()) {
14941530 getDelegate()._draw(canvas);
@@ -1584,6 +1620,15 @@
15841620 return super.dispatchTouchEvent(event);
15851621 }
15861622
1623+ @Override
1624+ public void dispatchDraw(Canvas canvas) {
1625+ component.dispatchDraw(canvas);
1626+ }
1627+
1628+ public void _dispatchDraw(Canvas canvas) {
1629+ super.dispatchDraw(canvas);
1630+ }
1631+
15871632 @SuppressLint("MissingSuperCall")
15881633 @Override
15891634 public void draw(Canvas canvas) {
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/ComponentUtil.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/ComponentUtil.java (revision 4)
@@ -1,5 +1,16 @@
11 package net.osdn.merlin.core.ui;
22
3+import android.graphics.Path;
4+
5+import net.osdn.merlin.core.UiThread;
6+
7+import java.util.AbstractMap.SimpleEntry;
8+import java.util.Map;
9+import java.util.Map.Entry;
10+import java.util.LinkedList;
11+import java.util.List;
12+import java.util.concurrent.Callable;
13+
314 public class ComponentUtil {
415
516 public static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
@@ -29,4 +40,96 @@
2940 return fullName.substring(0, i);
3041 }
3142
43+ /** 指定したComponentの子を再帰的に取得します。
44+ *
45+ * @param parent ルートとなるComponent
46+ * @return 指定したルートを含む子孫のComponentリスト
47+ */
48+ public static List<Component> getAllComponents(Component parent) {
49+ if(UiThread.isUiThread()) {
50+ List<Component> list = new LinkedList<Component>();
51+ if(parent instanceof Container) {
52+ int count = ((Container)parent).getComponentCount();
53+ for(int i = 0; i < count; i++) {
54+ Component child = ((Container)parent).getComponentAt(i);
55+ if(child instanceof Container) {
56+ list.addAll(getAllComponents(child));
57+ } else {
58+ list.add(child);
59+ }
60+ }
61+ }
62+ list.add(parent);
63+ return list;
64+ } else {
65+ final Component _parent = parent;
66+ return UiThread.invokeAndWait(new Callable<List<Component>>() {
67+ @Override
68+ public List<Component> call() throws Exception {
69+ List<Component> list = new LinkedList<Component>();
70+ if(_parent instanceof Container) {
71+ int count = ((Container)_parent).getComponentCount();
72+ for(int i = 0; i < count; i++) {
73+ Component child = ((Container)_parent).getComponentAt(i);
74+ if(child instanceof Container) {
75+ list.addAll(getAllComponents(child));
76+ } else {
77+ list.add(child);
78+ }
79+ }
80+ }
81+ list.add(_parent);
82+ return list;
83+ }
84+ });
85+ }
86+ }
87+
88+ /** 指定したComponentの子のドロップシャドウを再帰的に取得します。
89+ *
90+ * @param parent
91+ * @return
92+ */
93+ public static List<Shadow> getShadows(final Container parent, final int offsetX, final int offsetY) {
94+ if(UiThread.isUiThread()) {
95+ List<Shadow> list = new LinkedList<Shadow>();
96+ int count = ((Container)parent).getComponentCount();
97+ for(int i = 0; i < count; i++) {
98+ Component child = ((Container)parent).getComponentAt(i);
99+ if(!child.willNotDraw()) {
100+ int elevation = child.getElevation();
101+ Path path = child.getShadowPath();
102+ if(elevation >= 1 && path != null) {
103+ Shadow shadow = new Shadow(offsetX + child.getLeft(), offsetY + child.getTop(), elevation, path);
104+ list.add(shadow);
105+ }
106+ } else if(child instanceof Container) {
107+ list.addAll(getShadows((Container)child, offsetX + child.getLeft(), offsetY + child.getTop()));
108+ }
109+ }
110+ return list;
111+ } else {
112+ return UiThread.invokeAndWait(new Callable<List<Shadow>>() {
113+ @Override
114+ public List<Shadow> call() throws Exception {
115+ List<Shadow> list = new LinkedList<Shadow>();
116+ int count = ((Container)parent).getComponentCount();
117+ for(int i = 0; i < count; i++) {
118+ Component child = ((Container)parent).getComponentAt(i);
119+ if(!child.willNotDraw()) {
120+ int elevation = child.getElevation();
121+ Path path = child.getShadowPath();
122+ if(elevation >= 1 && path != null) {
123+ Shadow shadow = new Shadow(offsetX + child.getLeft(), offsetY + child.getTop(), elevation, path);
124+ list.add(shadow);
125+ }
126+ } else if(child instanceof Container) {
127+ list.addAll(getShadows((Container)child, offsetX + child.getLeft(), offsetY + child.getTop()));
128+ }
129+ }
130+ return list;
131+ }
132+ });
133+ }
134+ }
32135 }
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/Container.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/Container.java (revision 4)
@@ -4,6 +4,7 @@
44 import android.content.Context;
55 import android.graphics.Bitmap;
66 import android.graphics.Canvas;
7+import android.graphics.Path;
78 import android.graphics.drawable.Drawable;
89 import android.view.MotionEvent;
910 import android.view.ViewGroup;
@@ -15,6 +16,7 @@
1516 import java.util.Collections;
1617 import java.util.LinkedList;
1718 import java.util.List;
19+import java.util.Map.Entry;
1820 import java.util.concurrent.Callable;
1921
2022 public class Container extends Component {
@@ -182,7 +184,7 @@
182184 }
183185
184186 if(UiThread.isUiThread()) {
185- for(Component component : getAllComponents(Container.this)) {
187+ for(Component component : ComponentUtil.getAllComponents(Container.this)) {
186188 String key = component.getName();
187189 if(key != null) {
188190 key = key.trim();
@@ -198,7 +200,7 @@
198200 final String _name = name.trim();
199201 return UiThread.invokeAndWait(new Callable<T>() {
200202 public T call() {
201- for(Component component : getAllComponents(Container.this)) {
203+ for(Component component : ComponentUtil.getAllComponents(Container.this)) {
202204 String key = component.getName();
203205 if(key != null) {
204206 key = key.trim();
@@ -254,52 +256,22 @@
254256 });
255257 }
256258 }
257-
258- /** 指定したComponentの子を再帰的に取得します。
259+
260+ @Override
261+ protected void dispatchDraw(Canvas canvas) {
262+ onDrawShadows(canvas);
263+ super.dispatchDraw(canvas);
264+ }
265+
266+ /** 子コンポーネントのドロップシャドウを描画します。
259267 *
260- * @param parent ルートとなるComponent
261- * @return 指定したルートを含む子孫のComponentリスト
268+ * @param canvas
262269 */
263- public static List<Component> getAllComponents(Component parent) {
264- if(UiThread.isUiThread()) {
265- List<Component> list = new LinkedList<Component>();
266- if(parent instanceof Container) {
267- int count = ((Container)parent).getComponentCount();
268- for(int i = 0; i < count; i++) {
269- Component child = ((Container)parent).getComponentAt(i);
270- if(child instanceof Container) {
271- list.addAll(getAllComponents(child));
272- } else {
273- list.add(child);
274- }
275- }
276- }
277- list.add(parent);
278- return list;
279- } else {
280- final Component _parent = parent;
281- return UiThread.invokeAndWait(new Callable<List<Component>>() {
282- @Override
283- public List<Component> call() throws Exception {
284- List<Component> list = new LinkedList<Component>();
285- if(_parent instanceof Container) {
286- int count = ((Container)_parent).getComponentCount();
287- for(int i = 0; i < count; i++) {
288- Component child = ((Container)_parent).getComponentAt(i);
289- if(child instanceof Container) {
290- list.addAll(getAllComponents(child));
291- } else {
292- list.add(child);
293- }
294- }
295- }
296- list.add(_parent);
297- return list;
298- }
299- });
300- }
270+ protected void onDrawShadows(Canvas canvas) {
271+ List<Shadow> shadows = ComponentUtil.getShadows(this, 0, 0);
272+ PaintUtil.drawShadows(canvas, 0, 0, getWidth(), getHeight(), shadows);
301273 }
302-
274+
303275 protected static int[] divideEvenly(int[] values, int rest, boolean isSkipZero) {
304276 if(values == null || values.length == 0) {
305277 return values;
@@ -437,6 +409,15 @@
437409 return super.dispatchTouchEvent(event);
438410 }
439411
412+ @Override
413+ public void dispatchDraw(Canvas canvas) {
414+ component.dispatchDraw(canvas);
415+ }
416+
417+ public void _dispatchDraw(Canvas canvas) {
418+ super.dispatchDraw(canvas);
419+ }
420+
440421 @SuppressLint("MissingSuperCall")
441422 @Override
442423 public void draw(Canvas canvas) {
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/PaintUtil.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/PaintUtil.java (revision 4)
@@ -0,0 +1,77 @@
1+package net.osdn.merlin.core.ui;
2+
3+import android.graphics.Bitmap;
4+import android.graphics.Canvas;
5+import android.graphics.Color;
6+import android.graphics.Paint;
7+import android.graphics.Path;
8+import android.graphics.Rect;
9+
10+import java.util.List;
11+import java.util.Map.Entry;
12+
13+public class PaintUtil {
14+
15+ private static final int SHADOW_COLOR_UMBRA = Color.argb((int)(0.20f * 255), 0, 0, 0);
16+ private static final int SHADOW_COLOR_PENUMBRA = Color.argb((int)(0.14f * 255), 0, 0, 0);
17+ private static final int SHADOW_COLOR_AMBIENT = Color.argb((int)(0.12f * 255), 0, 0, 0);
18+
19+ public static void drawShadows(Canvas canvas, int left, int top, int right, int bottom, List<Shadow> shadows) {
20+ if(shadows.size() == 0) {
21+ return;
22+ }
23+
24+ Bitmap bitmap = getShadow(right - left, bottom - top, shadows);
25+ canvas.drawBitmap(bitmap, left, top, null);
26+ }
27+
28+ public static Bitmap getShadow(int width, int height, List<Shadow> shadows) {
29+ return createShadow(width, height, shadows);
30+ }
31+
32+ public static Bitmap createShadow(int width, int height, List<Shadow> shadows) {
33+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
34+ Canvas canvas = new Canvas(bitmap);
35+ Paint paint = new Paint();
36+ paint.setAntiAlias(true);
37+
38+ for(Shadow shadow : shadows) {
39+ if(shadow.getElevation() <= 0) {
40+ continue;
41+ }
42+ if(shadow.getPath() == null) {
43+ continue;
44+ }
45+
46+ float e = (float)shadow.getElevation();
47+ Path path = new Path();
48+ path.addPath(shadow.getPath(), shadow.getLeft(), shadow.getTop());
49+
50+ float umbraY = e / 2.0f;
51+ float umbraRadius = e / 2.0f + 2.5f;
52+ paint.setColor(SHADOW_COLOR_UMBRA);
53+ paint.setShadowLayer(Unit.DP(umbraRadius), 0.0f, Unit.DP(umbraY), SHADOW_COLOR_UMBRA);
54+ canvas.drawPath(path, paint);
55+
56+ float penumbraY = e;
57+ float penumbraRadius = e * 1.5f - 1.0f;
58+ if(penumbraRadius < 1.0f) {
59+ penumbraRadius = 1.0f;
60+ }
61+ paint.setColor(SHADOW_COLOR_PENUMBRA);
62+ paint.setShadowLayer(Unit.DP(penumbraRadius), 0.0f, Unit.DP(penumbraY), SHADOW_COLOR_PENUMBRA);
63+ canvas.drawPath(path, paint);
64+
65+ float ambientY = e / 3.0f + 1.0f;
66+ float ambientRadius = e * 2.0f - 3.0f;
67+ if(ambientRadius < 1.0f) {
68+ ambientRadius = 1.0f;
69+ }
70+ paint.setColor(SHADOW_COLOR_AMBIENT);
71+ paint.setShadowLayer(Unit.DP(ambientRadius), 0.0f, Unit.DP(ambientY), SHADOW_COLOR_AMBIENT);
72+ canvas.drawPath(path, paint);
73+ }
74+
75+ return bitmap;
76+ }
77+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/Shadow.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/Shadow.java (revision 4)
@@ -0,0 +1,33 @@
1+package net.osdn.merlin.core.ui;
2+
3+import android.graphics.Path;
4+
5+public class Shadow {
6+
7+ private int left;
8+ private int top;
9+ private int elevation;
10+ private Path path;
11+
12+ public Shadow(int left, int top, int elevation, Path path) {
13+ this.left = left;
14+ this.top = top;
15+ this.elevation = elevation;
16+ this.path = path;
17+ }
18+
19+ public int getLeft() {
20+ return this.left;
21+ }
22+
23+ public int getTop() {
24+ return this.top;
25+ }
26+ public int getElevation() {
27+ return this.elevation;
28+ }
29+
30+ public Path getPath() {
31+ return this.path;
32+ }
33+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/Window.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/Window.java (revision 4)
@@ -0,0 +1,214 @@
1+package net.osdn.merlin.core.ui;
2+
3+import android.graphics.Canvas;
4+import android.graphics.Color;
5+import android.graphics.Paint;
6+import android.graphics.Path;
7+import android.graphics.RectF;
8+import android.view.View;
9+import android.view.View.MeasureSpec;
10+
11+import java.util.Arrays;
12+import java.util.List;
13+
14+public class Window extends Container {
15+
16+ private static final float ROUND = Unit.DP(10.0f);
17+
18+ private Component content;
19+
20+ public Window(Component content) {
21+ super(null, null);
22+ this.content = content;
23+ add(content);
24+ setWillNotDraw(false);
25+ }
26+
27+ protected Path getWindowPath() {
28+ Path path = new Path();
29+ path.addRoundRect(
30+ new RectF(
31+ content.getLeft(),
32+ content.getTop(),
33+ content.getRight(),
34+ content.getBottom()
35+ ),
36+ ROUND,
37+ ROUND,
38+ Path.Direction.CW
39+ );
40+
41+ float h = 20;
42+ float a = h * 1.154700538379252f;
43+
44+ Path p = new Path();
45+ p.moveTo(content.getLeft() + 20, content.getBottom());
46+ p.lineTo(content.getLeft() + 20 + (a / 2), content.getBottom() + h);
47+ p.lineTo(content.getLeft() + 20 + a, content.getBottom());
48+ p.close();
49+ path.addPath(p);
50+
51+ return path;
52+ }
53+
54+ @Override
55+ protected void onDraw(Canvas canvas) {
56+ Paint paint = new Paint();
57+ paint.setAntiAlias(true);
58+
59+ paint.setColor(Color.WHITE);
60+ canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
61+
62+ Path path = getWindowPath();
63+ List<Shadow> shadows = Arrays.asList(new Shadow(0, 0, 8, path));
64+ PaintUtil.drawShadows(canvas, 0, 0, getWidth(), getHeight(), shadows);
65+
66+ canvas.clipPath(path);
67+ paint.setColor(Color.WHITE);
68+ canvas.drawPath(path, paint);
69+
70+ /*
71+ Paint paint = new Paint();
72+
73+ paint.setColor(Color.WHITE);
74+ paint.setStyle(Paint.Style.FILL);
75+ canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
76+
77+ paint.setColor(Color.RED);
78+ paint.setStyle(Paint.Style.STROKE);
79+ paint.setStrokeWidth(2.0f);
80+ canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
81+ */
82+ }
83+
84+ @Override
85+ protected void onDrawShadows(Canvas canvas) {
86+ }
87+
88+ @Override
89+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
90+ int wSize = MeasureSpec.getSize(widthMeasureSpec);
91+ int wMode = MeasureSpec.getMode(widthMeasureSpec);
92+ int hSize = MeasureSpec.getSize(heightMeasureSpec);
93+ int hMode = MeasureSpec.getMode(heightMeasureSpec);
94+
95+ Padding padding = getPadding();
96+
97+ int maxWidth = (wMode == MeasureSpec.EXACTLY) ? wSize : 0;
98+ int maxHeight = (hMode == MeasureSpec.EXACTLY) ? hSize : 0;
99+
100+ int count = getComponentCount();
101+ for(int i = 0; i < count; i++) {
102+ Component child = getComponentAt(i);
103+ if(child.getVisibility() != GONE) {
104+ Margin margin = child.getMargin();
105+ int w = 0;
106+ int h = 0;
107+ child.measure(
108+ MeasureSpec.makeMeasureSpec(wSize, MeasureSpec.AT_MOST),
109+ MeasureSpec.makeMeasureSpec(hSize, MeasureSpec.AT_MOST)
110+ );
111+ w = padding.width() + margin.width() + child.getMeasuredWidth();
112+ h = padding.height() + margin.height() + child.getMeasuredHeight();
113+ if(child.getX() >= 0) {
114+ w += child.getX();
115+ }
116+ if(child.getY() >= 0) {
117+ h += child.getY();
118+ }
119+ maxWidth = Math.max(w, maxWidth);
120+ maxHeight = Math.max(h, maxHeight);
121+ }
122+ }
123+ setMeasuredDimension(maxWidth, maxHeight);
124+ }
125+
126+ @Override
127+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
128+ Padding padding = getPadding();
129+
130+ Horizontal hAlign = getHorizontalAlignment();
131+ if(hAlign == null) {
132+ hAlign = Horizontal.Center;
133+ }
134+
135+ Vertical vAlign = getVerticalAlignment();
136+ if(vAlign == null) {
137+ vAlign = Vertical.Center;
138+ }
139+
140+ int count = getComponentCount();
141+ for(int i = 0; i < count; i++) {
142+ Component child = getComponentAt(i);
143+ if(child.getVisibility() != GONE) {
144+ Margin margin = child.getMargin();
145+ int x = child.getX();
146+ int y = child.getY();
147+ int w = child.getMeasuredWidth();
148+ int h = child.getMeasuredHeight();
149+
150+ int l = 0;
151+ int t = 0;
152+ int r = 0;
153+ int b = 0;
154+
155+ if(x >= 0) {
156+ l = padding.left + margin.left + x;
157+ r = l + w;
158+ } else {
159+ Horizontal hLayout = child.getHorizontalLayout();
160+ if(hLayout == null) {
161+ hLayout = hAlign;
162+ }
163+ switch(hLayout) {
164+ case Left:
165+ l = padding.left + margin.left;
166+ r = l + w;
167+ break;
168+ case Right:
169+ r = (right - left) - padding.right - margin.right;
170+ l = r - w;
171+ break;
172+ case Center:
173+ l = padding.left + margin.left + (((right - left) - padding.width()) - (w + margin.width())) / 2;
174+ r = l + w;
175+ break;
176+ case Fill:
177+ l = padding.left + margin.left;
178+ r = (right - left) - padding.right - margin.right;
179+ break;
180+ }
181+ }
182+
183+ if(y >= 0) {
184+ t = padding.top + margin.top + y;
185+ b = t + h;
186+ } else {
187+ Vertical vLayout = child.getVerticalLayout();
188+ if(vLayout == null) {
189+ vLayout = vAlign;
190+ }
191+ switch(vLayout) {
192+ case Top:
193+ t = padding.top + margin.top;
194+ b = t + h;
195+ break;
196+ case Bottom:
197+ b = (bottom - top) - padding.bottom - margin.bottom;
198+ t = b - h;
199+ break;
200+ case Center:
201+ t = padding.top + margin.top + (((bottom - top) - padding.height()) - (h + margin.height())) / 2;
202+ b = t + h;
203+ break;
204+ case Fill:
205+ t = padding.top + margin.top;
206+ b = (bottom - top) - padding.bottom - margin.bottom;
207+ break;
208+ }
209+ }
210+ child.layout(l, t, r, b);
211+ }
212+ }
213+ }
214+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/delegate/DelegateView.java (revision 3)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/delegate/DelegateView.java (revision 4)
@@ -165,7 +165,9 @@
165165 int[] getDrawableState();
166166
167167 boolean _dispatchTouchEvent(MotionEvent event);
168-
168+
169+ void _dispatchDraw(Canvas canvas);
170+
169171 void _setMeasuredDimension(int measuredWidth, int measuredHeight);
170172
171173 void _draw(Canvas canvas);
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/event/ClickEvent.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/event/ClickEvent.java (revision 4)
@@ -0,0 +1,10 @@
1+package net.osdn.merlin.core.ui.event;
2+
3+import net.osdn.merlin.core.ui.Component;
4+
5+public class ClickEvent extends ComponentEvent {
6+
7+ public ClickEvent(Component source) {
8+ super(source);
9+ }
10+}
--- Merlin/library/src/main/java/net/osdn/merlin/core/ui/event/ComponentEvent.java (nonexistent)
+++ Merlin/library/src/main/java/net/osdn/merlin/core/ui/event/ComponentEvent.java (revision 4)
@@ -0,0 +1,64 @@
1+package net.osdn.merlin.core.ui.event;
2+
3+import net.osdn.merlin.core.Event;
4+import net.osdn.merlin.core.EventDispatcher;
5+import net.osdn.merlin.core.FrameworkException;
6+import net.osdn.merlin.core.ReflectionUtil;
7+import net.osdn.merlin.core.State;
8+import net.osdn.merlin.core.StateManager;
9+import net.osdn.merlin.core.ui.Component;
10+
11+import java.lang.reflect.Method;
12+
13+public abstract class ComponentEvent implements Event {
14+
15+ private State state;
16+ private Component source;
17+ private Method handler;
18+ private Exception exception;
19+
20+ protected ComponentEvent(Component source) {
21+ this.state = StateManager.getCurrentState();
22+ this.source = source;
23+
24+ try {
25+ handler = ReflectionUtil.getMethod(state.getClass(), source.getName(), getClass());
26+ } catch (NoSuchMethodException e) {
27+ exception = new NoSuchMethodException("Event handler is not implemented: " + getMethodSignature());
28+ }
29+ }
30+
31+ @Override
32+ public State getState() {
33+ return state;
34+ }
35+
36+ @Override
37+ public Component getSource() {
38+ return source;
39+ }
40+
41+ @Override
42+ public Method getHandler() {
43+ return handler;
44+ }
45+
46+ @Override
47+ public Object getHandlerArguments() {
48+ return this;
49+ }
50+
51+ @Override
52+ public Exception getException() {
53+ return exception;
54+ }
55+
56+ private String getMethodSignature() {
57+ return state.getClass().getSimpleName()
58+ + "."
59+ + source.getName()
60+ + "("
61+ + getClass().getSimpleName()
62+ + " e);";
63+ }
64+}
旧リポジトリブラウザで表示