How to restrict the minimum size of the window for Eclipse e4 - eclipse

I am making an application based on Eclipse e4 framework. I was wondering how the minimal size of the application window can be controlled. There seems no properties can be defined in e4xmi file for this purpose.
Does anyone know how to do it?
I found a thread in Eclipse Community Forum (http://www.eclipse.org/forums/index.php/t/244875/) saying it can be achieved by creating my own renderer. How can I do that exactly?
Thank you very much :)

Assuming you are using the built-in SWT Renderers, you can also listen for the creation of your E4 MWindow elements and gain access to the underlying SWT Shell. In this example the listener is registered in an AddOn, which you can add to your e4xmi.
import javax.annotation.PostConstruct;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.swt.widgets.Shell;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
public class MinSizeAddon {
#PostConstruct
public void init(final IEventBroker eventBroker) {
EventHandler handler = new EventHandler() {
#Override
public void handleEvent(Event event) {
if (!UIEvents.isSET(event))
return;
Object objElement = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(objElement instanceof MWindow))
return;
MWindow windowModel = (MWindow)objElement;
Shell theShell = (Shell)windowModel.getWidget();
if (theShell == null)
return;
theShell.setMinimumSize(400, 300);
}
};
eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, handler);
}
}
Note, that this will be executed for any MWindow in your application, and there can be more of them (i.e. when an MPart is detached from the MPartStack into a seperate window). If you want to limit the execution to specific MWindows, I recommend to add a tag to the window in the e4xmi and check for this tag before setting the minimum size.

If anyone is still looking to do this in an e4 application and doesn't want to roll their own renderer, you can simply do the following in the post-construct of your part class:
#PostConstruct
public void postConstruct(Composite parent) {
parent.getShell().setMinimumSize(300, 300);
//...
}
The parent Composite passed in by the framework gives you access to the Shell, which lets you set the minimum size. This stops the application from being resized to less than the specified minimum size (in pixels).

Related

Plugin Development: IResourceChangeListener called more than once on just one change

I am using IResourceChangeListener to listen to changes in resource.
my code is:
public void createPartControl(Composite parent) {
// Graph will hold all other objects
graph = new Graph(parent, SWT.NONE);
// create the graph with the right nodes and connections.
init();
//listen to changes in the resource.
workspace = ResourcesPlugin.getWorkspace();
resourceChangeListener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
//IResourceDelta delta = event.getDelta();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
init();
System.out.println("Something changed!");
}
});
}
};
workspace.addResourceChangeListener(resourceChangeListener);
}
public void dispose() {
workspace.removeResourceChangeListener(resourceChangeListener);
}
But, when I am doing just one change in the resource, and save it, the listener called more than once! (usually twice, but sometimes even 6 times!!!)
I tried to use delta to see if it's called in the project,folder,file..
and I didn't saw differences between the calls (maybe I didn't used it properly).
I found this link, but I didn't found there solution to solve my problem
IResourceChangeListener being called twice with one change
How can I fix my code?
Thanks.
There is nothing you can do in the listener code to change how many resource change events you get. It depends entirely on how the code making the changes is doing the change.
You may find that IResourceDelta.getKind and IResourceDelta.getFlags return different values in the events. Also something getMovedFromPath and getMovedToPath for rename or move operations.
If it is your code doing the change you can use a WorkspaceJob or WorkspaceModifyOperation to do atomic changes to the workspace which will also reduce the number of resource change events.
You might also want to check that your old listeners are being removed correctly.

Switching scenes the FXML way (SceneBuilder)

I have two scenes, scene 1 has a Label on it that simply reads "This is scene 1", it also has a button on it with the text "Press me to go to scene 2". scene 2 is similar to scene 1 but the Label and text on scene 2 say the opposite.
The problem is very simple, or at least should be. I am able to do this the javaFX way but cannot seem to do it the FXML way.
I have a main class -
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class ManinApp extends Application
{
Stage primaryStage;
private AnchorPane rootLayout;
public static void main(String [] args)
{
launch(args);
}
public void start(Stage primaryStage)
{
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Two Scenes");
initRootLayout();
//showSecondScene();
}
public void initRootLayout()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ManinApp.class.getResource("Scene1.fxml"));
rootLayout = (AnchorPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
catch(IOException e)
{
e.printStackTrace();
}
}
/**
public void showSecondScene()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(ManinApp.class.getResource("Scene2.fxml"));
AnchorPane secondScene = (AnchorPane)loader.load();
rootLayout.getChildren().add(secondScene);
}
catch(IOException e)
{
e.printStackTrace();
}
}
*/
public Stage getPrimaryStage()
{
return primaryStage;
}
}
the showSecondScene() has been commented out for now. My understanding is that you also need a Controller class to wire up the code to SceneBuilder?
the solution the FX way was
btnscene1.setOnAction(e ->
{
if(e.getSource() == btnscene1)
thestage.setScene(scene2);
else
thestage.setScene(scene1);
});
btnscene2.setOnAction(e ->
{
if(e.getSource()==btnscene2)
thestage.setScene(scene1);
else
thestage.setScene(scene2);
});
apologies for the formatting!
how am I able to do this using a controller class from which i am able to use the primary stage and two scene declared in my main class?
i hope it makes sense
I think your are doing quite well. FXML (and SceneBuilder) are used correctly here.
I would suggest few things:
Use a root container (e.g. StackPane) to host either scene1 or scene2
(better names would be layout1 / layout2). You don't need to use
different Scene here.
Load both fxml files at init time (or lazy loading if needed)
switch from one to the other by removing the content of the root container, and adding the other one.
Now, if the layouts are big, with a lot of css involved, and you need to switch very often from layout1 to layout2, you may want to add both layout in the root container. Then, use:
setVisible()
setManaged()
... on the root of the layout you want to hide / show.
Doing this, you avoid the layout and css steps that is done as soon as you add a node in the scene graph.
While I technically understand, what you want to achieve, I'm still lost about the reason behind it.
If you just want to switch the "main" content of the window, use a StackPane as the root, add multiple Layouts to that stack, and solve your problem by switching the one you want to work on #toFront().
Normally the Layouts on the stack are transparent (except for the controls like buttons and so on, of course), so you would either need to set a background of the stacked Layouts OR (which I would prefer) toggle the visibility of the one in the back (or set opaqueness to 0, or something like that).

JavaFX: Reacting to Single, Double, and Triple Click

I am trying to configure certain actions in response to number of mouse clicks. It seems to me that the single click and triple click get detected and applied. but the double click does not really work.
I tried to do something like:
if (doubleClick)
else if (tripleClick)
else if (singleClick).
The order of checking did not help either, the action for the double click never gets triggered because that of the single click get triggered first. Any ideas on how to do this?
Assuming you are doing something like
if (mouseEvent.getClickCount()==1)
etc, then it's probably not doing what you think. MouseEvent.getClickCount() just returns the number of clicks that have occurred in a "small" region and in a "small" amount of time. "Small" is (deliberately) not defined.
So a double click is just two clicks. The first returns 1 for getClickCount(), then second returns 2. Similarly, a triple click is three clicks: the first returns 1, the next 2, the third 3. You can test this with a very simple piece of code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ClickCountTest extends Application {
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
root.setOnMouseClicked(event -> System.out.println(event.getClickCount()));
primaryStage.setScene( new Scene(root, 250, 150) );
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
If you click, you'll see the output "1". If you double click, you'll see a "1" followed by a "2".
There's no built-in way to ignore the first click if it's part of a double (or triple) click. The issue, obviously, is that at the time of the first click, there's no way of knowing if another click is going to come without some kind of timing, which gets pretty complicated and would force a delay on responding to any mouse click.
There was some talk a while back about implementing an onClickSequenceFinished type of event, so that instead of listening for mouse click events, you could listen for the click sequence finished event and then query that event to find the number of clicks. In the end, it was decided not to support this as the use case was not considered good UI programming practice.
The reason for that is that it's a pretty bad idea for, say, a double click to exclude the action of a single click. If the user is just too slow with their double click, then they will inadvertently invoke the single click action (twice). So if you are supporting both double click and single click actions, then the actions should be chosen so that it makes sense for the single-click action to be invoked any time the double-click action is invoked. The typical example is a ListView, where double-clicking a list element opens a "details" editor, and single-clicking selects the item. It makes sense for the item being edited to also be selected, so the double-click action implies the single-click action.
Put another way, it's considered a bad design if a double click action is designed to exclude a single click action, and that idiom is not directly supported. You should consider using modifier keys instead of click counts for this kind of distinction.
Update:
If you really want to distinguish events by click count like this (and I really don't recommend it), then you can use something like a PauseTransition to implement the timer. Something like:
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class ClickCountTest extends Application {
#Override
public void start(Stage primaryStage) {
// This value may need tuning:
Duration maxTimeBetweenSequentialClicks = Duration.millis(500);
PauseTransition clickTimer = new PauseTransition(maxTimeBetweenSequentialClicks);
final IntegerProperty sequentialClickCount = new SimpleIntegerProperty(0);
clickTimer.setOnFinished(event -> {
int count = sequentialClickCount.get();
if (count == 1) System.out.println("Single click");
if (count == 2) System.out.println("Double click");
if (count == 3) System.out.println("Triple click");
if (count > 3) System.out.println("Multiple click: "+count);
sequentialClickCount.set(0);
});
Pane root = new Pane();
root.setOnMouseClicked(event -> {
sequentialClickCount.set(sequentialClickCount.get()+1);
clickTimer.playFromStart();
});
primaryStage.setScene( new Scene(root, 250, 150) );
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is also probably a good use case for Tomas Mikula's ReactFX framework, (also see his blog post).
If you want to detect each of the different click counts, you could use a switch statement.
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
/**
*
* #author jeffreyguenther
*/
public class ListTest extends Application{
#Override
public void start(Stage stage) throws Exception {
Circle c = new Circle();
c.setRadius(100);
c.setCenterX(100);
c.setCenterY(100);
c.setFill(Color.AQUA);
c.setStroke(Color.BLACK);
c.setStrokeWidth(3);
c.setOnMousePressed((e) ->{
switch(e.getClickCount()){
case 1:
System.out.println("One click");
break;
case 2:
System.out.println("Two clicks");
break;
case 3:
System.out.println("Three clicks");
break;
}
});
stage.setScene(new Scene(new Group(c)));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Then as you single, double, and triple click this output is given:
One click
Two clicks
Three clicks
You can use the case statements to determine which counts you want to handle. For example, if you only want to handle the double and triple clicks, you can remove the first case.

implementing jlabel by codes in an automated jFrame in netbeans 6.9

Hi
i'm new with java swing,i try a lot and do a lot of search but in vain.i want to display a jlabel(not by drag n drop but with codes) on an automated jFrame that i have already.well my code for my JLabel is as follows:
private JLabel la=new JLabel("Display label");
codes that i got during my search to dispaly in a jpanel was like follows:
jPanel1.add(jLabel1);
but it does not work.My jPanel1 was built by drag n drop with the name Jpanel1.
i even try this piece of code:
this.add(jLabel1)--
this.getContentPane().add(jLabel1)
but still not working.
Please help me,it must be a simple line of code or i'm missing something somewhere ,please..thank you
This is a simple piece of code obtained from link text
public class HelloWorldFrame extends JFrame {
public static void main(String args[]) {
new HelloWorldFrame();
}
HelloWorldFrame() {
JLabel jlbHelloWorld = new JLabel("Hello World");
add(jlbHelloWorld);
this.setSize(100, 100);
// pack();
setVisible(true);
}
}
What you need to do is to re-set the setVisible property of the parent component to true

Memory usage of a GWT application

I'm currently working on a GWT application as a proof of technology for future projects. I like the way of building my AJAX code in Java instead of JavaScript. But I seem to be running into a memory problem when I repeat calls to an RPC service. The browser memory usage keeps growing and growing.
When searching Google I keep reading about how great GWT is and that its impossible to get memory leaks so can anyone explain why my browser (Firefox and Chromium) memory is rocketing?
Thanks in advance for helping me,
Bram
The code:
...
class ExampleTable extends Composite
private RPCService rpcService;
private Timer tableUpdater;
public ExampleTable(){
... Init timer and RPC Service
... Add components
initWidget();
}
private void getTableDataFromRPCService() {
this.rpcService.getData(new AsyncCallback<ArrayList<Data>>() {
#Override
public void onSuccess(ArrayList<Data> result) {
ExampleTable.this.updateTable(result);
}
#Override
public void onFailure(Throwable caught) {
//Do nothing
}
});
}
private void updateTable(ArrayList<Data> tableData){
... Update the table
}
private void startUpdateTask() {
this.serviceUpdater = new Timer() {
#Override
public void run() {
ExampleTable.this.getTableDataFromRPCService();
}
};
serviceUpdater.scheduleRepeating(2000);
}
}
EDIT:
I've spent some time to write a test application which can be downloaded here. I ran the application for about half an hour with the table update enabled after that Firefox took about 350MB of memory. I also ran the test with the update table disabled for an hour memory usage in Firefox went to little over 100MB.
(To run this sample you need the Google visualization API for GWT which can be downloaded from Google but I'm not allowed to post the link because of a new user policy )
I just got home from work and start another test without the table data update to see if memory usage keeps increasing or if it stops at a certain point.
This is the client implementation class (GWTMemoryIssue.java):
public class GWTMemoryIssue implements EntryPoint {
//Run with or without table
private static final boolean WITH_TABLE = false;
private final TestServiceAsync rpcService = GWT.create(TestService.class);
private Panel panel;
private Timer timer;
private Table table;
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
this.panel = new VerticalPanel();
this.panel.setSize("100%", "100%");
rootPanel.add(panel);
if (WITH_TABLE) {
loadTable();
}else{
startUpdateTask();
}
}
private void startUpdateTask() {
this.timer = new Timer() {
#Override
public void run() {
GWTMemoryIssue.this.getTableData();
}
};
this.timer.scheduleRepeating(2000);
}
public void loadTable() {
Runnable onLoadCallback = new Runnable() {
public void run() {
GWTMemoryIssue.this.table = new Table(createTableData(), createTableOptions());
GWTMemoryIssue.this.table.setSize("100%", "100%");
GWTMemoryIssue.this.panel.add(GWTMemoryIssue.this.table);
GWTMemoryIssue.this.startUpdateTask();
}
};
VisualizationUtils.loadVisualizationApi(onLoadCallback, Table.PACKAGE);
}
private Options createTableOptions() {
Options options = Options.create();
return options;
}
private DataTable createTableData() {
DataTable data = DataTable.create();
data.addColumn(ColumnType.STRING, "Name");
data.addColumn(ColumnType.NUMBER, "Intval 1");
data.addColumn(ColumnType.NUMBER, "Intval 2");
data.addColumn(ColumnType.NUMBER, "Intval 3");
return data;
}
private void getTableData() {
rpcService.getListOfItems(new AsyncCallback<ArrayList<ListItem>>(){
public void onFailure(Throwable caught) {
// Do nothing
}
public void onSuccess(ArrayList<ListItem> result) {
if (WITH_TABLE){
GWTMemoryIssue.this.updateTableData(result);
}else{
//Ignore the data from the server
}
}
});
}
private void updateTableData(ArrayList<ListItem> result) {
DataTable data = createTableData();
data.addRows(result.size());
int row = 0;
for (ListItem li : result) {
data.setValue(row, 0, li.getName());
data.setValue(row, 1, li.getIntVal());
data.setValue(row, 2, li.getIntSecondVal());
data.setValue(row, 3, li.getThirdIntVal());
row++;
}
this.table.draw(data, createTableOptions());
}
}
With all the additional information you provided here are some thoughts. I guess the memory increase is caused by the lists remaining in memory. It's either possible the memory is not freed at all or the JavaScript garbage collector doesn't get time to clean up, due too the short time frame between updates. Here are some test you could do:
To test if the garbage collector doesn't get time adapt you code such that the update only runs a finite number of times, and then check if the memory usage decreases over a few minutes. If the memory usage decreases, than it might be less of an issue in you real world example. But simple test it by setting the delay to the 30 seconds.
You could help the garbage collector by clearing the list after they are used: I don't know what works best, so here are some suggestions: Remove object from the list, or loop over the list and set values to null. This should not be necessary in normal case, because the garbage collector would do it.
You can also try the following Firefox Memory profiler add-on to see if you can locate the memory increases: http://ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on
I've been using GWT quite some time with many tables and RPCs and until now most memory leaks I found were my own fault.
The RPC layer does not seem to leak as far as I know and your example is just too simple to pose a problem.
You might need to take a look at what the updateTable method is actually doing, you might have a leak in your own code.
One thing that can cause huge memory leaks with GWT are Imagebundles in IE. It is a known fact that these leak extremely in GWT because they are using DXTransform to support alpha transparency. The memory goes up in large chunks everytime widgets are put on the screen. But there are tricks to avoid this.
No there is no explicit operation needed to clean garbage in Javascript. It is supposed to run automatically (although the GC in the browser is not on the same level as in a modern JVM).
GWT does it best to avoid common pitfalls that would cause memory leaks in JS (circular references between JS and DOM nodes are badly handled in some browsers).
So the question is: is the memory usage always going up ? Or does it top out at a certain point (or it just crashes with some out of memory ?). It can be normal that your application seems to be growing and growing... but GC should kick in at some point.
In my application memory usage tops out at about 64MB. But I am not working on Ubuntu, IE on windows is our main target, although I sometimes test on FireFox as wel (and there I don't see a leak either).
One other thing you might need to do is to avoid polling every 2 seconds like you do. If a request takes longer than 2 secs you start queing up the requests (a browser has a limitation on the number of concurrent connections). so it's best to wait for the response before firing a new timer.