11/*******************************************************************************
2- * Copyright (c) 2018 Oak Ridge National Laboratory.
2+ * Copyright (c) 2018-2023 Oak Ridge National Laboratory.
33 * All rights reserved. This program and the accompanying materials
44 * are made available under the terms of the Eclipse Public License v1.0
55 * which accompanies this distribution, and is available at
66 * http://www.eclipse.org/legal/epl-v10.html
77 *******************************************************************************/
88package org .phoebus .applications .alarm .ui .tree ;
99
10+ import javafx .scene .control .Label ;
11+ import javafx .scene .control .TreeCell ;
12+ import javafx .scene .image .ImageView ;
1013import javafx .scene .layout .Background ;
14+ import javafx .scene .layout .HBox ;
15+ import javafx .scene .paint .Color ;
16+
1117import org .phoebus .applications .alarm .client .AlarmClientLeaf ;
1218import org .phoebus .applications .alarm .client .AlarmClientNode ;
1319import org .phoebus .applications .alarm .client .ClientState ;
1420import org .phoebus .applications .alarm .model .AlarmTreeItem ;
1521import org .phoebus .applications .alarm .model .SeverityLevel ;
1622import org .phoebus .applications .alarm .ui .AlarmUI ;
1723
18- import javafx .scene .control .TreeCell ;
19- import javafx .scene .image .Image ;
20- import javafx .scene .image .ImageView ;
21- import javafx .scene .paint .Color ;
22-
2324/** TreeCell for AlarmTreeItem
2425 * @author Kay Kasemir
2526 */
2627@ SuppressWarnings ("nls" )
2728class AlarmTreeViewCell extends TreeCell <AlarmTreeItem <?>>
2829{
30+ // Originally, the tree cell "graphics" were used for the icon,
31+ // and the built-in label/text that can be controlled via
32+ // setText and setBackground for the text.
33+ // But using that built-in label/text background intermittently removes
34+ // the "triangle" for expanding/collapsing subtrees
35+ // as well as the "cursor" for selecting tree cells or navigating
36+ // cells via cursor keys.
37+ // So we add our own "graphics" to hold an icon and text
38+ private final Label label = new Label ();
39+ private final ImageView image = new ImageView ();
40+ private final HBox content = new HBox (image , label );
41+
2942 @ Override
3043 protected void updateItem (final AlarmTreeItem <?> item , final boolean empty )
3144 {
3245 super .updateItem (item , empty );
33- // Note: Cannot use background because that's used by style sheet and selection/cursor
46+
3447 if (empty || item == null )
35- {
36- setText (null );
3748 setGraphic (null );
38- setBackground (Background .EMPTY );
39- }
4049 else
4150 {
4251 final SeverityLevel severity ;
@@ -46,7 +55,6 @@ protected void updateItem(final AlarmTreeItem<?> item, final boolean empty)
4655 final ClientState state = leaf .getState ();
4756
4857 final StringBuilder text = new StringBuilder ();
49- final Image icon ;
5058 text .append ("PV: " ).append (leaf .getName ());
5159
5260 if (leaf .isEnabled () && !state .isDynamicallyDisabled ())
@@ -61,31 +69,32 @@ protected void updateItem(final AlarmTreeItem<?> item, final boolean empty)
6169 .append (state .current_severity ).append ('/' ).append (state .current_message )
6270 .append (")" );
6371 }
64- setTextFill (AlarmUI .getColor (state .severity ));
65- setBackground (AlarmUI .getBackground (state .severity ));
66- icon = AlarmUI .getIcon (state .severity );
72+ label . setTextFill (AlarmUI .getColor (state .severity ));
73+ label . setBackground (AlarmUI .getBackground (state .severity ));
74+ image . setImage ( AlarmUI .getIcon (state .severity ) );
6775 }
6876 else
6977 {
7078 text .append (" (disabled)" );
71- setTextFill (Color .GRAY );
72- setBackground (Background .EMPTY );
73- icon = AlarmUI .disabled_icon ;
79+ label . setTextFill (Color .GRAY );
80+ label . setBackground (Background .EMPTY );
81+ image . setImage ( AlarmUI .disabled_icon ) ;
7482 }
75- setText (text .toString ());
76- setGraphic (icon == null ? null : new ImageView (icon ));
83+ label .setText (text .toString ());
7784 }
7885 else
7986 {
8087 final AlarmClientNode node = (AlarmClientNode ) item ;
81- setText (item .getName ());
88+ label . setText (item .getName ());
8289
8390 severity = node .getState ().severity ;
84- setTextFill (AlarmUI .getColor (severity ));
85- setBackground (AlarmUI .getBackground (severity ));
86- final Image icon = AlarmUI .getIcon (severity );
87- setGraphic (icon == null ? null : new ImageView (icon ));
91+ label .setTextFill (AlarmUI .getColor (severity ));
92+ label .setBackground (AlarmUI .getBackground (severity ));
93+ image .setImage (AlarmUI .getIcon (severity ));
8894 }
95+ // Profiler showed small advantage when skipping redundant 'setGraphic' call
96+ if (getGraphic () != content )
97+ setGraphic (content );
8998 }
9099 }
91100}
0 commit comments