允许不同用户使用不同的GWT视觉主题

允许不同用户使用不同的GWT视觉主题,gwt,Gwt,我的问题是:如何根据登录的用户允许不同的GWT视觉主题? 我想决定在客户登录时使用哪个主题(那是在GWT应用程序加载之前,所以我很确定这应该是可能的)。 我尝试使用基于自定义属性的类替换,但失败了,因为只有最后继承的模块的图像集可见,即使我可以选择正确的css文件。。。我到处都找遍了,找不到答案 我会尝试以下一般方法: 为每个视觉主题定义一个CSS文件 按说明将它们全部放入一个容器中 在对用户进行身份验证之前,不要注入主题CSS。您可以插入显示登录屏幕所需的通用CSS 然后根据用户使用CssRe

我的问题是:如何根据登录的用户允许不同的GWT视觉主题? 我想决定在客户登录时使用哪个主题(那是在GWT应用程序加载之前,所以我很确定这应该是可能的)。
我尝试使用基于自定义属性的类替换,但失败了,因为只有最后继承的模块的图像集可见,即使我可以选择正确的css文件。。。我到处都找遍了,找不到答案

我会尝试以下一般方法:

  • 为每个视觉主题定义一个CSS文件
  • 按说明将它们全部放入一个容器中
  • 在对用户进行身份验证之前,不要注入主题CSS。您可以插入显示登录屏幕所需的通用CSS
  • 然后根据用户使用CssResource的ensureInjected()方法注入主题CSS

  • 谢谢你的建议,Thomas,但是这个解决方案的问题是,你假设CSS样式表可供我添加到ClientBundle(我试过了,但是除非你将CSS文件和附带的图片复制到你的项目中,否则你不能这样做)。主题来自外部GWT模块。为了模块化,我希望保持这种方式(每当我们需要一个新主题时,将一大堆资源导入到我的项目中会很痛苦)

    我想到的解决办法是在运行时自己编写注入代码(只需在HTML头部注入一个链接标记)。 为完整起见,以下是执行此操作的代码:

    protected void doInjection(String cssFilePath) {
        // <link type="text/css" rel="stylesheet" href="sol.css">
        Element headEl = Document.get().getElementsByTagName("head").getItem(0);
        HeadElement head = HeadElement.as(headEl);
        LinkElement link = Document.get().createLinkElement();
        link.setType("text/css");
        link.setRel("stylesheet");
        link.setHref(GWT.getModuleBaseURL() + cssFilePath);
        head.appendChild(link);
    }
    
    然后,从项目的GWT模块文件继承所有资源模块。例如:

      <inherits name='com.google.gwt.user.theme.standard.StandardResources'/>
      <inherits name='com.google.gwt.user.theme.dark.DarkResources'/>   
    
    
    
    继承模块的*Resources版本可避免自动注入样式表

    为了决定要使用哪个主题,我在模块文件中创建了一个自定义GWT属性,根据该属性的值,如果应该使用不同的主题,我用不同的Java类(默认类的子类)替换默认Java类(只插入默认主题)。这有一个额外的好处,我可以在每个主题中包含我自己的ResourceBundle资源,因为与主题一起使用的替换Java类,除了注入正确的css文件之外,还可以为我的GWT代码提供替代资源

    编辑

    我想补充一点重要的意见: 上面描述的解决方案非常有效。但是如果您的应用程序使用不同的地区或其他GWT属性,这种方法可能会导致编译排列的数量激增!只有6个不同的主题和3个不同的地区,在您通常拥有的标准6个不同的浏览器版本之上,GWT编译器将创建6 x 3 x 6=108个不同的编译!!这太疯狂了


    一个更好的解决方案,我最终决定遵循,是在用户登录后在HttpSession中设置一个属性,然后根据该属性的值加载相应的css文件(在我的入口点类的onModuleLoad()中的第一件事)。与上述解决方案的唯一区别在于如何选择主题。

    我使用了不同的方法,主要依靠CSS的强大功能和一行GWT代码来切换主题

    首先,定义要应用的主题。我使用枚举

    public enum Theme {
        DARK,
        BRIGHT;
    }
    public static String getDefault() {
        return BRIGHT.name();
    }
    
    现在,启动应用程序时,应用默认主题(
    theme.getDefault()
    )。当用户选择不同的主题时,应用它:

    public static void setTheme(String theme) {
       /*
        * Setting style on Body element allows us to "theme" the RootPanel as well.
        */
    
        Document.get().getBody().setClassName(theme);
    }
    
    当你应用一个新主题时,你的应用程序的外观会立即改变,而不会重新加载页面

    最后,定义CSS文件中需要的所有主题元素:

    .DARK {background: #000; color: #CCC}
    .BRIGHT {background: #ebebeb; color: #000}
    
    .gwt-DialogBox {border-radius: 6px}
    .DARK .gwt-DialogBox {border: 3px solid #555}
    .BRIGHT .gwt-DialogBox {border: 3px solid #CCC}
    

    请注意,您只在不同主题的规则前面添加了一个主题选择器。

    是否有理由在根文档上使用
    setClassName
    ,而不是
    RootPanel.get().setStyleName(主题)
    RootPanel.get().setStylePrimaryName(主题)
    ?关键原因是RootPanel通常已经有一些类名。这些其他课程将不以“主题”为主题。换句话说,如果您同时将“DARK”和“myApp”应用于根面板,则选择器“.DARK.myApp”将不起作用。我没有尝试为此使用setStylePrimaryName()和setStyleDependentName()。
    .DARK {background: #000; color: #CCC}
    .BRIGHT {background: #ebebeb; color: #000}
    
    .gwt-DialogBox {border-radius: 6px}
    .DARK .gwt-DialogBox {border: 3px solid #555}
    .BRIGHT .gwt-DialogBox {border: 3px solid #CCC}