NetBeans 7.4 から,java 1.7 がインストールされていないと NetBeans がインストールできなくなってしまった。java 1.6 環境での開発ができなくなったという意味ではないのだが,どうせなのでこれを機会に java 1.7 に移行することにした。
mac での ATOK 対応
ATOK を ATOK8 の時代から使っているが,いつもトラブルの元になって苦しめられている気がする。今回も java 1.7 で monsiaj の最新版(monsiaj-20130418)を使ってみたところ,ATOK on でテキストフィールドにカーソルがある状態からファンクションキーを押すと,exception を出してフリーズするという問題が発生した。(java 6 では問題ない)
ATOK26[233]: Exception in proxy -[IPMDServerClientWrapper selectedRange]
name = NSPortTimeoutException
reason = connection timeout: did not receive reply
userInfo = (null)
(
0 CoreFoundation 0x00007fff8a737b06 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff863c43f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8a7378dc +[NSException raise:format:] + 204
3 Foundation 0x00007fff85d68539 -[NSConnection sendInvocation:internal:] + 3209
4 CoreFoundation 0x00007fff8a726197 ___forwarding___ + 775
5 CoreFoundation 0x00007fff8a725e18 _CF_forwarding_prep_0 + 232
6 InputMethodKit 0x0000000100e26a99 -[IPMDServerClientWrapper selectedRange] + 207
7 ATOK26 0x00000001000b963d -[ATOKInputSessionWrapper selectedRangeWithClient:] + 77
8 ATOK26 0x00000001000aa994 -[ATOKIMController handleEvent:client:isInterruptedEvent:] + 476
9 ATOK26 0x00000001000aaac2 -[ATOKIMController handleEvent:client:] + 19
10 InputMethodKit 0x0000000100e31902 -[IMKServer handleEvent:characterIndex:edge:client:] + 2209
11 CoreFoundation 0x00007fff8a72b09c __invoking___ + 140
12 CoreFoundation 0x00007fff8a72af37 -[NSInvocation invoke] + 263
13 CoreFoundation 0x00007fff8a72b109 -[NSInvocation invokeWithTarget:] + 57
14 CoreFoundation 0x00007fff8a726197 ___forwarding___ + 775
15 CoreFoundation 0x00007fff8a725e18 _CF_forwarding_prep_0 + 232
16 CoreFoundation 0x00007fff8a72b09c __invoking___ + 140
17 CoreFoundation 0x00007fff8a72af37 -[NSInvocation invoke] + 263
18 Foundation 0x00007fff85d735f3 -[NSConnection dispatchInvocation:] + 331
19 Foundation 0x00007fff85d72651 -[NSConnection handleRequest:sequence:] + 1378
20 Foundation 0x00007fff85d6c7dd -[NSConnection handlePortCoder:] + 895
21 Foundation 0x00007fff85d6c00f -[NSConnection dispatchWithComponents:] + 53
22 Foundation 0x00007fff85d6bb15 __NSFireMachPort + 257
23 CoreFoundation 0x00007fff8a6a6e40 __CFMachPortPerform + 288
24 CoreFoundation 0x00007fff8a6a6d09 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
25 CoreFoundation 0x00007fff8a6a6a49 __CFRunLoopDoSource1 + 153
26 CoreFoundation 0x00007fff8a6d9c02 __CFRunLoopRun + 1826
27 CoreFoundation 0x00007fff8a6d90e2 CFRunLoopRunSpecific + 290
28 HIToolbox 0x00007fff89c3deb4 RunCurrentEventLoopInMode + 209
29 HIToolbox 0x00007fff89c3dc52 ReceiveNextEventCommon + 356
30 HIToolbox 0x00007fff89c3dae3 BlockUntilNextEventMatchingListInMode + 62
31 AppKit 0x00007fff88dac533 _DPSNextEvent + 685
32 AppKit 0x00007fff88dabdf2 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
33 AppKit 0x00007fff88da31a3 -[NSApplication run] + 517
34 AppKit 0x00007fff88d47bd6 NSApplicationMain + 869
35 ATOK26 0x00000001001002bc main + 913
36 ATOK26 0x00000001000017f4 start + 52
)
ATOK on の状態だと,他の操作でもしばしば exception を出さずにフリーズしてしまい,実用にならない状態であった。いずれも ATOK を切って操作すればフリーズしない。しかたがないので,全ての Component で enableInputMethod(false) として,ATOK を切った。
WidgetBuilder.java
public static Component buildWidget(Interface xml, WidgetInfo info, Container parent) {
:
// ATOK causes freeze everywhere, so kill it unless necessary
widget.enableInputMethods(false);
:
しかし,これでは日本語入力ができない。そこで,「かな」キーを押すと,押した Component だけ enableInputMethod(true) になるようにした。
PandaFocusManager.java
public void processKeyEvent(Component focusedComponent, KeyEvent e) {
:
if (e.getKeyCode() == KeyEvent.VK_KATAKANA) {
focusedComponent.enableInputMethods(true);
}
:
その他,AccelHandler.java,PandaTable.java にも ATOK を切るコードを入れた。この改造で,java 7 でも何とか1日フリーズなしで過ごせるようになった。こういう個人的な環境に合わせた改造ができるのは,オープンソースのよいところだと思う。
その他の改造
ついでに気になっていた部分をいくつか改造した。
(K02)診療行為入力画面の PandaTable の行数が常に 400行になっていて,データの後に大量の空白行がくっついた状態で表示されてしまう。そこで,空白行は無視して,データがある行だけを表示するように改造した。
PandaTable.java
public void keyPressed(KeyEvent e) {
:
// 現在の selectedRow が実データの最終行なら,それ以上下へは移動しないようにする
if (e.getKeyCode() != KeyEvent.VK_DOWN || getRealRowCount() != getSelectedRow()) {
Component parent = ((Component) e.getSource()).getParent();
KeyEvent pass = new KeyEvent(parent, e.getID(), e.getWhen(), e.getModifiers(), e.getKeyCode(), e.getKeyChar());
parent.dispatchEvent(pass);
}
:
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
// 空行への changeSelection は拒否る
if (getRealRowCount() < rowIndex) { return; }
:
/**
* pns サーバから帰ってくるデータの行数が,実データの有無にかかわらず常に400行なので,
* 実データのある必要行数だけ表示するようにする
* @return
*/
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int realRowCount = getRealRowCount();
// 実データを表示するのに必要な高さ
size.height = (realRowCount + 1) * getRowHeight();
// 親が Viewport であれば,その高さよりも小さくならないようにする
Object parent = getParent();
if (parent != null && (parent instanceof JViewport)) {
JViewport view = (JViewport) parent;
if (size.height < view.getHeight()) {
size.height = view.getHeight();
}
}
return size;
}
/**
* pns 実データの行数を返す
* @return
*/
private int getRealRowCount() {
int realRowCount = 0;
// 最終行からスキャンして,実データを見つけた時点で行数とする
for (int r=getRowCount()-1; r>=0; r--) {
// columm 1 に何か入っていれば実データである
Object value = model.getValueAt(r, 1);
if (value != null && !"".equals(((String)value).trim())) {
realRowCount = r + 1;
break;
}
}
return realRowCount;
}
(K02)診療行為入力画面で,表示されたデータ行で編集を行ってリターンキーを押すと,セルの選択が最後の行に飛んでしまう。自分的には飛ばない方が良いと思うので,飛ばないように改造した。
PandaTableMarshaller.java
public synchronized void receive(WidgetValueManager manager, Component widget) throws IOException {
:
//pns 現在編集中の行を保存
editingRow = table.getSelectedRow();
:
if (trow >= 0 && tcolumn >= 0) {
//pns 編集中の行があれば選択を変えない begins
if (editingRow != -1) {
// ただし最後の行の編集であれば,selectedRow を1つ下に送る
if (trow == editingRow + 1) { trow = editingRow + 1; }
else if (trow > editingRow) { trow = editingRow; }
}
//pns ends
PandaPreview で表示倍率を選択できるようになっているが,初期値をシステムプロパティーから設定できるようにした。
PandaPreview.java
//pns zoom 初期値を system property から取得 begins
//pns zoom = SCALE_FIT_PAGE_WIDTH;
int index = 1;
if (System.getProperty("monsia.pandapreview.initialzoom") != null) {
try {
int n = Integer.parseInt(System.getProperty("monsia.pandapreview.initialzoom"));
if (n >= 0 && n <=9) {
index = n;
} else {
if (n == 50) { index = 2; }
else if (n == 75) { index = 3; }
else if (n == 100) { index = 4; }
else if (n == 125) { index = 5; }
else if (n == 150) { index = 6; }
else if (n == 175) { index = 7; }
else if (n == 200) { index = 8; }
else if (n == 300) { index = 9; }
}
} catch (NumberFormatException e) {}
}
zoom = SCALE_VALUE[index];
combo.setSelectedIndex(index);
これまで CListMarsheller.java にグリッド表示コードを入れていたが,コードを見ていたところ,PandaCList.java に,グリッド表示をシステムプロパティーで制御しようとした痕跡を見つけた。そこで,グリッド表示コードをこちらに移した。monsia.panadaclist.showgrid=true などと値を設定するとグリッドが表示される。
PandaCList.java
:
// if (System.getProperty("monsia.widget.pandaclist.showgrid") == null) {
if (System.getProperty("monsia.pandaclist.showgrid") == null) {
this.setShowGrid(false);
}
//pns show grid
else {
this.setShowGrid(true);
this.setGridColor(new java.awt.Color(235,235,235));
}
:
改造したコードは bitbucket さんに上げた。