使用ADF Faces 之六:使用CSS为应用动态换肤

本文介绍如何在ADF应用中创建并使用自定义皮肤(MyNewSkin.css),通过修改组件外观来定制界面风格,并实现了运行时的皮肤动态切换功能。
开发环境:JDevloper 11.1.2.1.0+ Oracle Database 10g Express Edition 10.2.0.1。

完成《 Changing an Application's Look and Feel by Using Skins 》。

1. 创建ADF Skin:MyNewSkin.css

新建的ADF Skin继承fusion的皮肤,包括所有组件的外观定义。

可以在默认皮肤的基础上定制你的皮肤,修改后会把变化的部分保存到CSS文件中。


2. 使用Firefox Debug查看当前页面使用的是哪个CSS?


3. 定制皮肤
(1)定制af:document:Faces Component Selectors > Document > af|document 

(2)定制默认字体:Global Selector Aliases | Font > .AFDefaultFontFamily

(3)定制默认别名字体:Global Selector Aliases | Font > .AFDefaultFont:alias.

(4)定制Panel Header:Faces Component Selectors,Panel Header | Pseudo-Elements

(5)定制Column Header:Faces Component Selectors,Column | Pseudo-Elements node,column-header-table

(6)定制Panel List的Link:Panel List > Pseudo-Elements,link 

(7)定制Tab形状:Global Selector Aliases > node Component Group Tabs

运行效果如下:使用登录用户 sking/Welcome1234


4. 运行时动态切换皮肤
(1)trinidad-config.xml
该文件决定运行时使用哪个皮肤,可以静态指定,也可以使用EL表达式实现动态选择。
你甚至可以根据用户的本地语言来决定使用哪个皮肤,比如德语皮肤或英语皮肤。
<?xml version="1.0" encoding="windows-1252"?>
<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
  <skin-family>#{sessionScope.skinFamily!=null?sessionScope.skinFamily : 'fusion'}</skin-family>
  <!--
  <skin-family>MyNewSkin</skin-family>
  <skin-family>#{facesContext.viewRoot.locale.language=='de' ? 'german' : 'english'}</skin-family>
-->
</trinidad-config>


(2)trinidad-skins.xml
该文件注册了所有自定义皮肤,运行时可以选择这些皮肤或者系统自带的皮肤。
<?xml version="1.0" encoding="windows-1252" ?>
<skins xmlns="http://myfaces.apache.org/trinidad/skin">
  <skin>
    <id>completedSkinSample.desktop</id>
    <family>completedSkinSample</family>
    <extends>fusion.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>skins/completedSkinSample/completedSkinSample.css</style-sheet-name>
  </skin>
  <skin>
    <id>princess-skin.desktop</id>
    <family>princess-skin</family>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <extends>simple.desktop</extends>
    <style-sheet-name>skins/princess/princess.css</style-sheet-name>
  </skin>
  <skin>
    <id>MyNewSkin.desktop</id>
    <family>MyNewSkin</family>
    <extends>fusionFx-simple-v2.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>skins/MyNewSkin/MyNewSkin.css</style-sheet-name>
    <bundle-name>adf/sample/view.skinBundle</bundle-name>
  </skin>
</skins>


(3)trinidad-skins.xml
<af:selectOneChoice label="Choose a Skin" value="#{sessionScope.skinFamily}" id="soc1" autoSubmit="true" valueChangeListener="#SkinManager.onNewSkinSelection}">
<f:selectItems value="#{SkinManager.skinChoices}" id="si1"/>
</af:selectOneChoice>

(4)SkinManager.java
package adf.sample.view.beans;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

import oracle.adf.controller.ControllerContext;
import oracle.adf.share.ADFContext;

import org.apache.myfaces.trinidad.skin.Skin;
import org.apache.myfaces.trinidad.skin.SkinFactory;


public class SkinManager {
    public SkinManager() {
        ADFContext adfctx = ADFContext.getCurrent();
        Map sessionScope = adfctx.getSessionScope();
        Object skinFamily = sessionScope.get("skinFamily");
        if (skinFamily == null) {
            sessionScope.put("skinFamily", "fusion");
        }
    }

    public List getSkinChoices() {
        List choices = new ArrayList();
        String skinFamily = null;
        String skinLabel = null;
        SkinFactory sf = SkinFactory.getFactory();
        FacesContext context = FacesContext.getCurrentInstance();
        for (Iterator i = sf.getSkinIds(); i.hasNext(); ) {
            String skinID = (String)i.next();
            Skin skin = sf.getSkin(context, skinID);
            skinFamily = skin.getFamily();
            skinLabel = skinFamily;
            if (skin.getRenderKitId().indexOf("desktop") > 0) {
                choices.add(new SelectItem(skinFamily, skinLabel));
            }
        }
        return choices;
    }

    public void onNewSkinSelection(ValueChangeEvent valueChangeEvent) {
        ADFContext adfctx = ADFContext.getCurrent();
        Map sessionScope = adfctx.getSessionScope();
        sessionScope.put("skinFamily", (String)valueChangeEvent.getNewValue());
        redirectToSelf();
    }

    private void redirectToSelf() {
        FacesContext fctx = FacesContext.getCurrentInstance();
        ExternalContext ectx = fctx.getExternalContext();
        String viewId = fctx.getViewRoot().getViewId();
        ControllerContext controllerCtx = null;
        controllerCtx = ControllerContext.getInstance();
        String activityURL = controllerCtx.getGlobalViewActivityURL(viewId);
        try {
            ectx.redirect(activityURL);
            fctx.responseComplete();
        } catch (IOException e) {
            //Can't redirect
            e.printStackTrace();
            fctx.renderResponse();
        }
    }
}

(5)运行时下拉列表显示的ADF Skins:


Project 下载:ADFSkinSample.7z

http://maping930883.blogspot.com/2009/09/adf026adf-faces-css.html

内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;最后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值