2011-04-18 10 views
8

Her büyük istemci için farklı bir temayı gerektiren bir web uygulamasına sahibiz. Orijinal geliştirici, javascript'te URL'ye bakarak ve varsayılan temayı geçersiz kılmak için bir stil sayfası ekleyerek bunu gerçekleştirdi.Birden çok "tema" için ClientBundle

Buradaki bir sorun, sitenin birkaç saniye varsayılan görünümüne sahip olması ve ardından aniden doğru temasa geçmesidir. Bir diğeri, çok fazla bant genişliği/zaman harcaması gibi görünüyor.

Benim şu anki düşüncesi bizim varsayılan görünüme sahip bir "varsayılan" ClientBundle oluşturabilir ve bu arayüz uzatmak ve @ImageResouce gibi çeşitli ek açıklamaları kullanarak ve farklı bir konuma işaret müşterinin görüntülerle (gerektiğinde) Her bir girişi geçersiz hissetmektir.

Bunu yapan deneyime sahip olan var mı? Öngördüğüm bir sorun, belirli bir kaynak kümesine statik olarak işaret ettikleri için uibinder stili etiketlerini kullanamamaktadır.

Herhangi bir fikrin var mı?

+0

bir örnek ... – helios

cevap

17

overriden desteler Evet yapabilirsiniz

.

ClientBundles ile geçersiz kılma işini yaptım ve iyi çalışıyor. Yapmanız gereken bir şey de mülklerin türlerini miras almaktır. Örneğin ile:

BigBundle { 
    Nestedundle otherBundle(); 
    ImageResource otherImage(); 
    Styles css(); 
} 

Ve o zaman bu tarafa miras gerekir:

OtherBigBundle extends BigBundle { 
    OtherNestedBundle otherBundle(); // if you want to change it 
    ImageResource otherImage(); // of you want to change it 
    OtherStyles css(); // of you want to change it 
} 

ve OtherNestedBundle extends NestedBundle ve

OtherStyles extends Styles En azından css en şununla: özellikleri bildirilen eğer çocuğu KULLANMAMA Arabirim aynı CSS classname için stiller üretecek ve hepsi karışacaktır. Yani çocuk arayüzlü overriden stilleri beyan :)

Esnek UIBinders

Sen UiField(provided=true) ek açıklama kullanırsanız kullanmak paket dışından ayarlayabilirsiniz

. Bu şekilde, ilk önce paketi ayarlayın ve ardından uibindler'ı arayın. Zaten oluşturulduğunu varsayarak kaynak alanını kullanacaktır.

Sen yükleme sadece doğru demeti için GWT.runAsync kullanabilirsiniz bağlayıcı Ertelendi.

ui bazı örnek.xml

<ui:with field='res' type='your.package.TheBundle'/> 

ilgili sınıf

@UiField(provided=true) TheBundle bundle; 

private void createTheThing() { 
    this.bundle = factory.createBundle(); 
    MyUiBindler binder = GWT.create(MyUiBindler.class); 
    this.panel = binder.createAndBindUi(this); 
    ... 
} 

Bazı paket arayüzleri

interface TheBundle extends ClientBundle { 
    @ImageResource("default.png") 
    ImageResource image1(); 

    @Source("default.css") 
    TheCss css(); 
} 

interface Theme1Bundle extends TheBundle { 
    @ImageResource("one.png") 
    ImageResource image1(); // type: imageresource is ok 

    @Source("one.css") 
    OneCss css(); // type: OneCss => use other compiled css class-names 

    interface OneCss extends TheCss { // inner-interface, just for fun 
    // don't need to declare each String method 
    } 
} 

bir şey geçersiz kılmaz Eğer paket fabrikasında

için ok

Seçenekler var

1) sadece tamamen

if (...) { 
    return GWT.create(TheBundle.class); 
} else if (...) { 
    return GWT.create(Theme1Bundle.class); 
} 

2) runAsync (sadece

if (...) { 
    GWT.runAsync(new RunAsyncCallback() { 
     public void onSuccess() { 
     return GWT.create(TheBundle.class); 
     } 
     // please program the onFailure method 
    }); 
} else if (...) { 
    GWT.runAsync(new RunAsyncCallback() { 
     public void onSuccess() { 
     return GWT.create(Theme1Bundle.class); 
     } 
     // please program the onFailure method 
    }); 
} 

3) için bağlayıcı ertelenen ve jeneratör kullanın) gerekli bölümünü yük ... ama ilk bölümü yürütüldükten sonra @ThemeBundle("one")

Açıklama: Bu örnek gerçek dünyadan gelmektedir. Bir tanımlayıcı dizesine dayalı widget oluşturmak için DynamicEntryPointWidgetFactory (kısaca DEPWidgetFactory) kullanıyorum. Her widget bir uygulama ekranıdır ve her ana menü ítem oluşturmak zorunda olduğu widgetName sahiptir.

Sizin durumunuzda, kimlik oluşturulacak tema olacaktır.

Önemli: Eğer runAsync kullanırsanız, daha önce örnek kodda olduğu gibi UI oluşturmadan hemen önce sourcebundle'ı oluşturamazsınız. Temayı sormanız ve hazır olduğunda (geri aramada) onu widget yapıcınıza iletmeniz ve widget'ınızın onu alana atamanız gerekir.

fabrika arayüzü:

public interface DynamicEntryPointWidgetFactory 
{ 
    public void buildWidget(String widgetName, AsyncCallback<Widget> callback); 
} 

widget'lar için ek açıklama oluşturmak için:

@Target(ElementType.TYPE) 
public @interface EntryPointWidget 
{ 
    /** 
    * The name wich will be used to identify this widget. 
    */ 
    String value(); 
} 

modül yapılandırma:

Diyor ki Fabrikası için uygulama bununla oluşturulacak class (diğer seçenek, replace-with kullanmaktır, ancak bizim durumumuzda, her yerel ayar ya da tarayıcı için önceden tanımlanmış seçeneklere sahip değiliz, ancak daha dinamik bir şey).

<generate-with class="com.dia.nexdia.services.gwt.rebind.entrypoint.DynamicEntryPointFactoryGenerator"> 
    <when-type-assignable class="com.dia.nexdia.services.gwt.client.entrypoint.DynamicEntryPointWidgetFactory" /> 
</generate-with> 

jeneratör:

public class DynamicEntryPointFactoryGenerator extends Generator { 
    @Override 
    public String generate(TreeLogger logger, GeneratorContext context, 
      String typeName) throws UnableToCompleteException { 
     PrintWriter pw = context.tryCreate(logger, 
       "x.services.gwt.client.entrypoint", 
       "DynamicEntryPointWidgetFactoryImpl"); 

     if (pw != null) { 
      // write package, imports, whatever 
      pw.append("package x.services.gwt.client.entrypoint;"); 
      pw.append("import x.services.gwt.client.entrypoint.DynamicEntryPointWidgetFactory;"); 
      pw.append("import com.google.gwt.core.client.GWT;"); 
      pw.append("import com.google.gwt.core.client.RunAsyncCallback;"); 
      pw.append("import com.google.gwt.user.client.rpc.AsyncCallback;"); 
      pw.append("import com.google.gwt.user.client.ui.Widget;"); 

      // the class 
      pw.append("public class DynamicEntryPointWidgetFactoryImpl implements DynamicEntryPointWidgetFactory {"); 

      // buildWidget method 
      pw.append(" public void buildWidget(String widgetName, final AsyncCallback<Widget> callback) {"); 

      // iterates over all the classes to find those with EntryPointWidget annotation 
      TypeOracle oracle = context.getTypeOracle(); 
      JPackage[] packages = oracle.getPackages(); 
      for (JPackage pack : packages) 
      { 
       JClassType[] classes = pack.getTypes(); 
       for (JClassType classtype : classes) 
       { 
        EntryPointWidget annotation = classtype.getAnnotation(EntryPointWidget.class); 
        if (annotation != null) 
        { 
         String fullName = classtype.getQualifiedSourceName(); 
         logger.log(TreeLogger.INFO, "Entry-point widget found: " + fullName); 

         pw.append("if (\"" + annotation.value() + "\".equals(widgetName)) {"); 
         pw.append(" GWT.runAsync(" + fullName + ".class, new RunAsyncCallback() {"); 
         pw.append("  public void onFailure(Throwable t) {"); 
         pw.append("   callback.onFailure(t);"); 
         pw.append("  }"); 
         pw.append("  public void onSuccess() {"); 
         pw.append("   callback.onSuccess(new " + fullName + "());"); 
         pw.append("  }"); 
         pw.append(" });"); 
         pw.append(" return;"); 
         pw.append("}"); 
        } 
       } 
      } 
      pw.append("callback.onFailure(new IllegalArgumentException(\"Widget '\" + widgetName + \"' not recognized.\"));"); 

      pw.append(" }"); 
      pw.append("}"); 

      context.commit(logger, pw);   
     } 

     // return the name of the generated class 
     return "x.services.gwt.client.entrypoint.DynamicEntryPointWidgetFactoryImpl"; 
    } 
+0

Nasıl olur seçenek 3 eser eklendi? GWT xml config dosyasına bir jeneratör kaydediyor musunuz? – benstpierre

+1

Tam olarak. BundleFactory arabirimi için "jeneratör sınıfı" hangisini belirtirsiniz. Bu jeneratör sınıfı, kodu çıkaran bir yöntemi uygulamalıdır. Bu kod "eğer" yazıyor. Bundle arabirimlerini bir şekilde (@ThemeBundle örneği gibi) etiketlemek için bazı GWT yardımcı sınıflarını kullanabilir. Yarın istersen örnek kod gönderebilirim. – helios

+0

Geleneksel css değiş tokuşu ile hangi css dosyası anında tüm GUI'ye yüklenecek şekilde yüklenmiyor? Bu aynı etkiyi elde etmenin bir yolu var mı yoksa her stili yeni pakete "yeniden ayarla" mıyım? – benstpierre