View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.renderer.impl;
17  
18  import java.util.Stack;
19  
20  import org.eclipse.jface.viewers.Viewer;
21  import org.eclipse.swt.widgets.Widget;
22  import org.seasar.uruma.annotation.RenderingPolicy.SetTiming;
23  import org.seasar.uruma.component.EnablesDependable;
24  import org.seasar.uruma.component.UIComponent;
25  import org.seasar.uruma.context.PartContext;
26  import org.seasar.uruma.context.WidgetHandle;
27  import org.seasar.uruma.core.UrumaMessageCodes;
28  import org.seasar.uruma.exception.RenderException;
29  import org.seasar.uruma.log.UrumaLogger;
30  import org.seasar.uruma.renderer.RendererSupportUtil;
31  import org.seasar.uruma.util.AssertionUtil;
32  import org.seasar.uruma.util.ClassUtil;
33  
34  /**
35   * {@link Widget} のレンダリングを行うための基底クラスです。<br />
36   * 
37   * @param <COMPONENT_TYPE>
38   *            レンダラに対応するコンポーネントの実際の型
39   * @param <WIDGET_TYPE>
40   *            レンダラが生成するウィジットの実際の型
41   * @author bskuroneko
42   */
43  public abstract class AbstractWidgetRenderer<COMPONENT_TYPE extends UIComponent, WIDGET_TYPE extends Widget>
44          extends AbstractRenderer {
45      private UrumaLogger logger = UrumaLogger.getLogger(getClass());
46  
47      private Stack<Object> renderingContext = new Stack<Object>();
48  
49      /*
50       * @see org.seasar.uruma.renderer.Renderer#render(org.seasar.uruma.component.UIComponent,
51       *      org.seasar.uruma.context.WidgetHandle,
52       *      org.seasar.uruma.context.PartContext)
53       */
54      @SuppressWarnings("unchecked")
55      public WidgetHandle render(final UIComponent uiComponent,
56              final WidgetHandle parent, final PartContext context) {
57          setContext(context);
58  
59          inherit((COMPONENT_TYPE) uiComponent);
60  
61          Object parentObject = parent.getWidget();
62          Widget parentWidget = null;
63  
64          if (parentObject instanceof Widget) {
65              parentWidget = Widget.class.cast(parentObject);
66          } else if (parentObject instanceof Viewer) {
67              parentWidget = Viewer.class.cast(parentObject).getControl();
68          } else {
69              throw new RenderException(UrumaMessageCodes.UNSUPPORTED_TYPE_ERROR,
70                      parentObject, Widget.class.getName());
71          }
72  
73          WIDGET_TYPE widget = createWidget(parentWidget, getStyle(uiComponent));
74  
75          renderWidget((COMPONENT_TYPE) uiComponent, widget);
76  
77          WidgetHandle handle = createWidgetHandle(uiComponent, widget);
78  
79          if (uiComponent instanceof EnablesDependable) {
80              setupEnablesDependingDef(handle, (EnablesDependable) uiComponent);
81          }
82  
83          return handle;
84      }
85  
86      /**
87       * 生成したウィジットに対するレンダリングを行います。<br />
88       * 
89       * @param uiComponent
90       *            対応する {@link UIComponent}
91       * @param widget
92       *            生成したウィジット
93       */
94      protected void renderWidget(final COMPONENT_TYPE uiComponent,
95              final WIDGET_TYPE widget) {
96          try {
97              RendererSupportUtil.setAttributes(uiComponent, widget,
98                      SetTiming.RENDER);
99  
100             doRender(uiComponent, getWidgetType().cast(widget));
101 
102         } catch (Exception ex) {
103             throw new RenderException(
104                     UrumaMessageCodes.EXCEPTION_OCCURED_WITH_REASON, ex, ex
105                             .getMessage());
106         }
107     }
108 
109     /*
110      * @see org.seasar.uruma.renderer.Renderer#renderAfter(org.seasar.uruma.context.WidgetHandle,
111      *      org.seasar.uruma.component.UIComponent,
112      *      org.seasar.uruma.context.WidgetHandle,
113      *      org.seasar.uruma.context.PartContext)
114      */
115     @SuppressWarnings("unchecked")
116     public void renderAfter(final WidgetHandle handle,
117             final UIComponent uiComponent, final WidgetHandle parent,
118             final PartContext context) {
119         Object widget = handle.getWidget();
120         RendererSupportUtil.setAttributes(uiComponent, widget,
121                 SetTiming.RENDER_AFTER);
122         doRenderAfter(getWidgetType().cast(widget),
123                 (COMPONENT_TYPE) uiComponent, parent, context);
124     }
125 
126     /*
127      * @see org.seasar.uruma.renderer.Renderer#reRender(org.seasar.uruma.context.WidgetHandle)
128      */
129     @SuppressWarnings("unchecked")
130     public void reRender(final WidgetHandle handle) {
131         AssertionUtil.assertNotNull("handle", handle);
132         UIComponent uiComponent = handle.getUiComponent();
133         Object widget = handle.getWidget();
134         AssertionUtil.assertNotNull("uiComponent", uiComponent);
135         AssertionUtil.assertNotNull("widget", widget);
136 
137         try {
138             RendererSupportUtil.setAttributes(uiComponent, widget,
139                     SetTiming.RENDER);
140 
141             doRender((COMPONENT_TYPE) uiComponent, getWidgetType().cast(widget));
142         } catch (Exception ex) {
143             throw new RenderException(
144                     UrumaMessageCodes.EXCEPTION_OCCURED_WITH_REASON, ex, ex
145                             .getMessage());
146         }
147     }
148 
149     /**
150      * 親コンポーネントから属性を引き継ぎます。<br />
151      * 親コンポーネントから属性を引き継ぎたい場合、本メソッドをオーバーライドして処理を行ってください。<br />
152      * デフォルトでは何も行いません。
153      * 
154      * @param uiComponent
155      *            自コンポーネントの {@link UIComponent} オブジェクト
156      */
157     protected void inherit(final COMPONENT_TYPE uiComponent) {
158         // do nothing.
159     }
160 
161     /**
162      * ウィジットを生成します。<br />
163      * ウィジットの生成を独自に行いたい場合、サブクラスで本メソッドをオーバーライドしてください。<br />
164      * 
165      * @param parent
166      *            親ウィジットオブジェクト
167      * @param style
168      *            スタイル値
169      * @return 生成したウィジットのインタンス
170      */
171     protected WIDGET_TYPE createWidget(final Widget parent, final int style) {
172         Class<WIDGET_TYPE> widgetClass = getWidgetType();
173         WIDGET_TYPE widget = ClassUtil.<WIDGET_TYPE> newInstance(widgetClass,
174                 parent, style);
175 
176         if (logger.isTraceEnabled()) {
177             logger.log(UrumaMessageCodes.WIDGET_CREATED, UrumaLogger
178                     .getObjectDescription(widget));
179         }
180 
181         return widget;
182     }
183 
184     /**
185      * 生成するウィジットの型を返します。<br />
186      * ウィジットのインスタンス生成は本クラスで実施するので、サブクラスで本メソッドを実装してウィジットの型のみを返してください。<br />
187      * 
188      * @return 生成するウィジットの型
189      */
190     protected abstract Class<WIDGET_TYPE> getWidgetType();
191 
192     /**
193      * 生成されたウィジットに対して各種属性を設定します。<br />
194      * 本メソッドをサブクラスで実装し、<code>uiComponent</code> の保持する属性を <code>widget</code>
195      * に対して設定してください。<br />
196      * 
197      * @param uiComponent
198      *            {@link UIComponent} オブジェクト
199      * @param widget
200      *            生成されたウィジット
201      */
202     protected abstract void doRender(COMPONENT_TYPE uiComponent,
203             WIDGET_TYPE widget);
204 
205     /**
206      * 子のレンダリング終了後にレンダリング処理を行います。<br />
207      * 子のレンダリング終了後にレンダリング処理を行う場合、本メソッドをオーバーライドしてレンダリング処理を実装してください。<br />
208      * デフォルトでは何も行いません。<br />
209      * 
210      * @param widget
211      *            レンダリング対象ウィジット
212      * @param uiComponent
213      *            レンダリング対象の {@link UIComponent} オブジェクト
214      * @param parent
215      *            親のウィジットハンドル
216      * @param context
217      *            {@link PartContext} オブジェクト
218      */
219     protected void doRenderAfter(final WIDGET_TYPE widget,
220             final COMPONENT_TYPE uiComponent, final WidgetHandle parent,
221             final PartContext context) {
222         // do nothing.
223     }
224 
225     protected void pushRenderingContext(final Object object) {
226         renderingContext.push(object);
227     }
228 
229     protected Object popRenderingContext() {
230         return renderingContext.pop();
231     }
232 
233     protected Object peekRenderingContext() {
234         return renderingContext.peek();
235     }
236 }