GWTが生成するスタイルシート
GWTはコンパイル時に自動的にスタイルシートを生成する。これは、開発モードでも行われる。
例として、最新Eclipse(2018/1 Oxygen)でGWTサンプルを動かすまでで作成したEclipseのGWTプラグインが生成するサンプルを使用する。
gwt.xmlの例
サンプルでは、以下のようなgwt.xmlが自動生成されている。
<?xml version="1.0" encoding="UTF-8"?>
<!--
When updating your version of GWT, you should also update this DTD reference,
so that your app can take advantage of the latest GWT module capabilities.
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.2//EN"
"http://gwtproject.org/doctype/2.8.2/gwt-module.dtd">
<module rename-to='sample'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='sample.client.Sample'/>
<!-- Specify the paths for translatable code -->
<source path='client'/>
<source path='shared'/>
<!-- allow Super Dev Mode -->
<add-linker name="xsiframe"/>
</module>
コメントにもあるのだが、<inherits name=’com.google.gwt.user.theme.clean.Clean’/>という記述によって、スタイルシートが生成されているのである。
スタイルシートはどこにあるのか?
開発モードの実行でもコンパイルでも同じなのだが、この記述によって自動的にスタイルシートが生成され、以下に格納される。
モジュール名がsampleなので、war/sampleの下のgwtの中に作られる。
スタイルシートの中身は何か?
この中のclean.cssを見てみると以下のような記述になっている。
/**
* The file contains styles for GWT widgets in the Clean theme.
*/
body, table td, select, button {
font-family: Arial Unicode MS, Arial, sans-serif;
font-size: small;
}
pre {
font-family: "courier new", courier;
font-size: small;
}
body {
color: black;
margin: 10px;
border: 0px;
padding: 0px;
background: #fff;
direction: ltr;
}
a, a:visited {
color: #0066cc;
text-decoration:none;
}
a:hover {
color: #0066cc;
text-decoration:underline;
}
select {
background: white;
}
/**
* The reference theme can be used to determine when this style sheet has
* loaded. Create a hidden div element with absolute position, assign the style
* name below, and attach it to the DOM. Use a timer to detect when the
* element's height and width are set to 5px.
*/
.gwt-Reference-clean {
height: 5px;
width: 5px;
zoom: 1;
}
.gwt-Button {
margin: 0;
padding: 5px 7px;
text-decoration: none;
cursor: pointer;
cursor: hand;
font-size:small;
background: url("images/hborder.png") repeat-x 0px -2077px;
border:1px solid #bbb;
border-bottom: 1px solid #a0a0a0;
border-radius: 3px;
-moz-border-radius: 3px;
}
.gwt-Button:active {
border: 1px inset #ccc;
}
(略)
基本的には、GWTに備わっているウィジェトのためのスタイルを決めている。例えば、ChromeのデベロッパーツールでButtonウィジェットを見てみると、gwt-Buttonというclassが指定されている。
先の生成スタイルシートの.gwt-Buttonが使われるというわけである。
スタイルシートを変更するには?
最初のgwt.xmlのコメントにあるように、GWTには複数のスタイルシートが提供されており、これを変更するだけで別のスタイルシートになるようだ。試しに、darkというスタイルシートに変更してみる。
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<inherits name='com.google.gwt.user.theme.dark.Dark'/>
アプリ画面は以下に変わり、
war/sample/gwtは以下に変わる(削除しなければcleanは残ったまま)
複数指定するとどうなるのか?
例えば以下のように指定する。
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<inherits name='com.google.gwt.user.theme.chrome.Chrome'/>
<inherits name='com.google.gwt.user.theme.dark.Dark'/>
すると、指定通りすべてが生成される。が、実際に使用されるのは最後のもの、つまりDarkになるようだ。
また、スタイルシートではない、通常のモジュールの中でスタイルシートが指定されていた場合、それも有効になってしまう。
例えば、以下のように指定する。
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='foo.bar.Bar'/>
Barモジュールの中でDarkが指定されていた場合、Clean、Dark共に生成されて、Darkが有効になる。
※非常に面倒になるので、他で使用されるモジュールにはスタイルシートを指定すべきではない。
無くすことはできるのか?
ときにはGWTのウィジェットを全く使わない場合もありうる。すべてを異なるウィジェットセットにし、専用のスタイルシートを使う場合である。しかし、この場合でもGWTの生成するスタイルシートにはbody等へのfont-familyが指定されており、場合によってはGWTの指定が採用されてしまう。
この場合にはgwt.xmlでどのスタイルシートもコメントアウトしてしまう。すると、当然GWTはスタイルシートを生成しなくなる。結果以下のような表示になり、war/sample/gwtフォルダ自体が生成されない。
独自のGWT用スタイルシートモジュールを作るには?
では、GWTのウィジェットを使いつつ、例えばfont-familyを変更することはできるのだろうか。GWTの提供するモジュールがそのまま生成するスタイルシートでは以下のようになるが、より日本語に適したフォントを使いたいのである。
body, table td, select, button {
font-family: Arial Unicode MS, Arial, sans-serif;
font-size: small;
}
単純なことだった。単にスタイルシート及び必要なイメージを特定のフォルダに入れ、モジュールとして参照するだけだ。例えば、Cleanの場合を見てみる。
gwt-user.jarの中の「com.google.gwt.user.theme.clean」パッケージを見てみると以下のようになっている。
Clean.gwt.xmlを見てみると以下の記述になっている。
<module>
<inherits name='com.google.gwt.user.User'/>
<public path="public" />
<stylesheet src="gwt/clean/clean.css"/>
</module>
「public path」の意味は、Organizing Projectsの中の「Public Path」にある。
つまり、public pathとして指定されたpublicというフォルダ以下が、Cleanをinheritsしたモジュールの下にコピーされる。この場合は、gwt以下がコピーされていたわけである。
そして、コピーされるだけではなく、stylesheetとして使われなければならないので、そのパスを<stylesheet src=”gwt/clean/clean.css”/>で指定しているわけである。この説明も先のマニュアルの中にある。
ちなみに、CleanRTL.gwt.xmlは右から左に書く言語のためのもの、CleanResources.gwt.xmlはstylesheet指定が無く、単純にコピーするだけのものらしい。
関連する議論
これに関連する議論がStackOverflowにある。