Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 466710

Summary: RAP incorrectly using theming for DEFAULT and FOCUS Buttons
Product: [RT] RAP Reporter: John Gymer <jgymer>
Component: RWTAssignee: Project Inbox <rap-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: tbuschto
Version: 2.3   
Target Milestone: 3.1 M1   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description John Gymer CLA 2015-05-07 06:52:49 EDT
There appears to be some issues with how theming is applied to DEFAULT and FOCUS Buttons in RAP (2.3 and 3.0). I have changed the CSS to make the issue more obvious... DEFAULT Buttons have a RED background and FOCUS Buttons have a YELLOW background:

Button[ARROW]:default,
Button[PUSH]:default,
Button[TOGGLE]:default {
  background-color: #416693;
  background-image: gradient(
    linear, left top, left bottom,
    from( #ff0000 ),
    to( #d4d4d4 )
  );
  border: 1px solid #a0b3ca;
}

...and...

Button-FocusIndicator[ARROW], Button-FocusIndicator[PUSH], Button-FocusIndicator[TOGGLE] {
  background-color: #ffff00;
  border: 1px dotted #b8b8b8;
  margin: 2px;
  padding: 0px;
  opacity: 1;
}

My snippet below has a button called myBut, myField below it and defBut below that:

/* DEMONSTRATES Default Button and Focus Button theming issues */
package bug.snippet;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class Bugsy {
	Display display;
	Shell shell;
	Label lab;
	Button myBut;
	Button defBut;
	Text myField;
	int tryLoop = 0;
	
	public void begin() {
		display = new Display();
		
		shell = new Shell(display, SWT.APPLICATION_MODAL|SWT.CLOSE);
		shell.setFullScreen(true);
		shell.setText("My Shell");
		FormLayout layout = new FormLayout();
		shell.setLayout(layout);
		
		FormData fd;
		
		myBut = new Button(shell, SWT.PUSH);
		myBut.setText("Add Rows");
		fd = new FormData();
		fd.left = new FormAttachment(0, 10);
		fd.top = new FormAttachment(0, 50);
		fd.right = new FormAttachment(0,250);
		fd.bottom = new FormAttachment(0, 80);
		myBut.setLayoutData(fd);

		myField = new Text(shell, SWT.BORDER|SWT.SINGLE);
		fd = new FormData();
		fd.left = new FormAttachment(0, 10);
		fd.top = new FormAttachment(0, 100);
		fd.right = new FormAttachment(0, 250);
		fd.bottom = new FormAttachment(0, 130);
		myField.setLayoutData(fd);
		
		defBut = new Button(shell, SWT.PUSH);
		defBut.setText("Default Button");
		fd = new FormData();
		fd.left = new FormAttachment(0, 10);
		fd.top = new FormAttachment(0, 150);
		fd.right = new FormAttachment(0,250);
		fd.bottom = new FormAttachment(0, 180);
		defBut.setLayoutData(fd);
		
		myBut.addSelectionListener(butSelectListener);
		defBut.addSelectionListener(butSelectListener);
		
		shell.setDefaultButton(defBut);

		shell.open();
	}

	SelectionListener butSelectListener = new SelectionListener() {
		@Override
		public void widgetSelected(SelectionEvent e) {
			if (e.widget.equals(myBut)) {
				myField.setText("Selected myBut");
			}
			else if (e.widget.equals(defBut)) {
				myField.setText("Selected defBut");
			}
		}

		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
			if (e.widget.equals(myBut)) {
				myField.setText("DEF Selected myBut");
			}
			else if (e.widget.equals(defBut)) {
				myField.setText("DEF Selected defBut");
			}
		}
	};
}

My understanding of DEFAULT/FOCUS with Buttons is that the DEFAULT Button is the one that will get triggered when hitting ENTER.  Therefore if any Button currently has focus, it automatically is also the DEFAULT one. If you tab to something that is not a Button (like myField in this example), then I'd expect defBut to go RED to show that it is the DEFAULT one.

In general this is working OK...

Example... on startup, myBut is RED because it has FOCUS, and is therefore the one that will get triggered when ENTER is pressed.  OK, good so far.

Tab focus to myField, and defBut becomes RED... also correct, as that is designed as the DEFAULT Button by shell.setDefaultButton.  OK, still good.

Tab to defBut, and defBut goes YELLOW... this shows that it has FOCUS.  This is inconsistent now - why does YELLOW take priority over RED (as it did for myBut when we first started the app)?

Worse though... if I tab again, back round to myBut, myBut goes YELLOW to show FOCUS (OK), but defBut goes RED. This is definitely wrong, because the RED suggests that defBut will get triggered when I hit ENTER, but it doesn't - the FOCUS button (myBut) does.

So, the behaviour of ENTER processing is correct, but the colouring is incorrect.

Thanks, John
Comment 1 Tim Buschtoens CLA 2015-07-21 09:58:25 EDT
Fixed with commit aba761e5ab584eeb21e4c8a7f17aace98292b2be
Apply "default" state to focused buttons

It now behaves as in SWT. The :default state is applied to any focused button and to the actual "default" button if no other button is focused.

Note that :focused and :default are not mutually exclusive, and that the Focus-Indicator are is drawn ON TOP of any button that received the :focused state by traversal. That is why the button in the example appeared yellow - it is the background of the focus frame (usually transparent) drawn on top of the default button.