Google Map GWT does not fit container size - java

I'm having troubles making a second call to load a Google Map in a GWT app. The problem itself is that once the map is called, it won't fit the container size. This is a usual problem, as depicted in many previous SO questions:
Here
Here
Here
Here
Let me state that I've tried all of the above and sadly nothing seems to work. I must also say I'm using the unofficial version of GWT Maps API v3, which can be found here. Thus, this is the problem:
Now, weird enough, if I change the browser size, map displays correctly:
Thus, it looks like I need to "dispatch" the onResize event somehow...but I tried with all of the above methods and nothing seemed to work. Just for clarification this, is the part where I construct the map and add it to the container:
private void buildMapMarinesPark() {
//Visualizar datos...
LatLng center = LatLng.newInstance(52.62715,1.7734);
MapOptions opts = MapOptions.newInstance();
opts.setZoom(9);
opts.setCenter(center);
opts.setMapTypeId(MapTypeId.HYBRID);
MapTypeControlOptions controlOptions = MapTypeControlOptions.newInstance();
controlOptions.setMapTypeIds(MapTypeId.values()); // use all of them
controlOptions.setPosition(ControlPosition.TOP_RIGHT);
opts.setMapTypeControlOptions(controlOptions);
mapMarinePark = new MapWidget(opts);
mapMarinePark.setSize("100%", "100%");
// Add some controls for the zoom level
List<EuropeanMarineParkDataEntity> parksPerAnio = null;
listPolygon = new ArrayList<Polygon>();
Polygon poly = null;
for(int i=2003;i<=ANIO_MAP_PARK;i++){
parksPerAnio = this.hashAnioParks.get(""+i);
if(parksPerAnio != null){
for(EuropeanMarineParkDataEntity emp : parksPerAnio){
poly = this.createPolygon(emp);
poly.setMap(mapMarinePark);
listPolygon.add(poly);
}
}
}
((Element)DOM.getElementById("currentYear")).setPropertyObject("innerHTML", ""+(ANIO_MAP_PARK));
// Add the map to the HTML host page
final DockLayoutPanel dock = new DockLayoutPanel(Unit.PX);
dock.addNorth(mapMarinePark, 500);
RootPanel.get("mapContainerProfile2").add(dock);
RootPanel.get("timeline").setVisible(true);
RootPanel.get("mapPanel2").setVisible(true);
RootPanel.get("gadget_marinepark").setVisible(true);
mapMarinePark.triggerResize(); --> Does not work!
onLoadedMapMarinePark();
}

I guess you try to draw the map when the DOM hasn't been fully constructed and the wrong dimensions are retrieved.
Try to draw/create the map in a callback of a
Scheduler.get().scheduleDeferred() call.
Update:
Also you are mixing a DockLayoutPanel with a RootPanel.
That will cause issues. Use a RootLayoutPanel instead.
Construct the DOM normally and at the point where you normally add your map to the DockLayoutPanel call scheduleDeferred() and add the map to the panel in the callback

Related

How to clear collections in javafx.scene.Scene$MouseHandler?

I have got 2 Pane. The first pane is main menu, there is only Rectangle in its children. The second pane is my game. When I go to main menu I use following method to clear game pane
//Fighting fighting = new Fighting();
//There is Pane fighting in fighting
if(fighting != null) {
fighting.getFighting().getChildren().clear();
fighting = null;
System.gc();
}
When I scene.setRoot(fighting.getFighting()); and don't do anything(don't hover on objects which has OnMouse...(), don't call methods which move player) and exit to main menu(by clicking Esc)
scene.setOnKeyPressed(event -> {
if (event.getCode()==KeyCode.ENTER) setFighting();
if (event.getCode()==KeyCode.ESCAPE) setMainMenu();
});
In such case I don't have problems with memory and GC deletes useless objects.
But if I click/hover on any objects with listeners or call move() on player, GC won't delete the same object. And if I re-enter game pane and use it normally, GC will delete objects from prevoius session and won't delete them from current session
In my profiler I've found out that references on these useless objects are stored in Pane which is in one of ArrayLists in anonymous class MouseHandler in Scene. Can't add image good.
Also I've found out that there are only 2 Pane in heap. One of them is mainMenu. I've understood it because there is only Rectangle in its children. And the second's pane's children equals children.size() == 0.
It's code from Scene & MouseHandler
private MouseHandler mouseHandler;
class MouseHandler {
/* lists needed for enter/exit events generation */
private final List<EventTarget> pdrEventTargets = new ArrayList<EventTarget>();
private final List<EventTarget> currentEventTargets = new ArrayList<EventTarget>();
private final List<EventTarget> newEventTargets = new ArrayList<EventTarget>();
private final List<EventTarget> fullPDRCurrentEventTargets = new ArrayList<EventTarget>();
private final List<EventTarget> fullPDRNewEventTargets = new ArrayList<EventTarget>();
private EventTarget fullPDRCurrentTarget = null;
}
Is it possible to clear these collections or to fix memory leak? Thanks for answers
Well technically you may use the Reflection API to get access to that list and clear it manually, but i’m not sure would it be safe to do so.
AFAIK that pdrEventTargets list is holding components chain that represents a path from the scene to a component that was clicked the last and that list is being refreshed at each click. So if you’re in situation when you have replaced a branch of componens tree and still seeing a bunch of references on removed components in that list, these are will be removed from pdrEventTargets on the next click handling by MouseHandler. At least it behaves exactly like that while i debugging at jdk 1.8. Probably you have exactly the same behavior, so there should be no reasons to worry about, at least if these staled components do not holding a references to some “heavy” objects that should not live after these components was removed. In that case you should remove that references as part of the process of components remove.

GWT getElementbyId to equivalent widget / Panel

I'm trying to build a dynamic web app in GWT, when widgets are added to the screen I remember their 'name' by setting the Widget.setId, when I want to replace part of the page, I can find the element in question via DOM.getElementById('name'), and its parent using DOM.getParentElement(), and then remove its children.
Now I have a com.google.gwt.dom.client.Element object (the parent). What I want to do is turn this back into a GWT object - in fact it'll be something derived from Panel, so I can add additional Widgets.
How do I go from the Element object back to a Panel object ?
I totally accept I could be going about this the wrong way, in which case is there a better way?
I think your approach to remove widgets from the DOM using DOM.getElementById('name') is not the proper one.
On your case (I am just figuring out what you do), I would keep Java Objects references instead of accessing to them using the DOM.
For instance:
HorizontalPanel panel = new HorizontalPanel();
Widget w = new Widget();
//We add the one widget to the panel
panel.add(w);
//One more widget added
w = new Widget();
panel.add(w);
//Now we remove all the widgets from the panel
for(int i = 0; i < panel.getWidgetCount(); i++){
panel.remove(panel.getWidget(i));
}
UPDATE
Based on your comments, I would propose the following solution.
I suppose that you are storing widgets on HorizontalPanel, just apply this solution to your concrete case.
I propose to use customized class which inherits from HorizontalPanel and add a Map there to store relationship between names and widgets.
public class MyHorizontalPanel extends HorizontalPanel {
private Map<String, Widget> widgetsMap;
public MyHorizontalPanel(){
super();
widgetsMap = new HashMap<String, Widget>();
}
//We use Map to store the relationship between widget and name
public void aadWidget(Widget w, String name){
this.add(w);
widgetsMap.put(name, w);
}
//When we want to delete and just have the name, we can search the key on the map.
//It is important to remove all references to the widget (panel and map)
public void removeWidget(String name){
this.remove(widgetsMap.get(name));
widgetsMap.remove(name);
}
}

Custom Cell Rendering prevent loading image in getListCellRendererComponent()

I have a JList that is displaying a custom object (Frog) using a custom cell renderer.
frogList = new JList<Frog>();
frogModel = new DefaultListModel<Frog>();
frogList.setModel(frogModel);
frogList.setCellRenderer(new FrogBrowserCellRenderer());
//add frogs...
The frog objects contains a list of images, and I have my list pick the latest one to display. It's in a thumbnail file, so I can read it into memory and display it. However I know that the JList re-renders every time the window moves or the window needs redrawn which is really bad for performance and just not good design. The issue I have is that this list is dynamic so I cannot simply load all images at startup because users can add them at runtime and it'll auto update the list.
Some people mentioned loading the image into memory in the constructor and setting it in the getListCellRendererComponent() method but that doesn't appear to be possible because it only creates one cell renderer and uses it for everything in the list. I also verified this by printing out the constructor method. Since I will have a list of frogs with all different images this doesn't really make sense.
Here is the code I am using to create the thumbnail right now.
public Image createListThumbnail() {
try {
Image returnImg = null;
//get latest frog image
SiteImage img = frog.getLatestImage();
BufferedImage src = ImageIO.read(new File(XMLFrogDatabase.getImagesFolder()+img.getImageFileName()));
BufferedImage thumbnail = Scalr.resize(src, Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH, 200, 150, Scalr.OP_ANTIALIAS);
if (!frog.isFullySearchable()){
ImageFilter filter = new GrayFilter(true, 30);
ImageProducer producer = new FilteredImageSource(thumbnail.getSource(), filter);
returnImg = Toolkit.getDefaultToolkit().createImage(producer);
}
return returnImg;
} catch (IOException e) {
IdentiFrog.LOGGER.writeExceptionWithMessage("Unable to generate thumbnail for image (in memory).", e);
}
return null;
}
I call this method in my getListCellRendererComponent() which I know causes terrible performance but I don't understand how to cache it in memory for multiple frogs and also use only one object. Perhaps an image map? I can't seem to find any solid evidence of a proper way to do this.

Java ADF using stored parameter from data control class with stacked bar-graph

I am working with a dual-axis stacked bar graph (ADF component) using a List of objects containing the x-axis labels and the values to be displayed/stacked in the graph.
I'm relatively new to ADF & EJB so I want to apologise in advance if this question seems rudimentary to any of you.
I should mention that I'm using JDeveloper 11.1.1.5
I'm having a hard time with retrieving the value from a variable to be assigned to a property of the bar graph I'm trying to display on my JSF page.
I have briefly summarised the logic below for reference.
The data/list is retrieved from the following class data control:
public class ActivityChart {
private Double axisScale;
public ActivityChart() {
super();
axisScale = 0.0;
}
public List<ActivityDTO> getActivityDetail(List<String> businessUnits) {
List<ActivityDTO> returnNewList = new ArrayList<ActivityDTO>();
List<TransactionDTO> dataList = new ArrayList<TransactionDTO>();
TransactionSessionBean transBean = lookupTransactionSessionBean();
if (businessUnits != null && !businessUnits.isEmpty()){
dataList = transBean.getActivityData(SystemUtil.getCurrentUser(), businessUnits);
returnNewList = processTransactions(dataList);
axisScale = calcAxisScale(returnNewList);
}
return returnNewList;
}
...
The TransactionDTO object is basically a mirror of the entity object to store the fields from the queried db transactions.
The ActivityDTO object contains a String value (x-axis label) and 3 Double values for the values required for the bar graph.
What I'm trying to do is dynamically set the scale for the 2 y-axes (I'm using a dual-axis stacked bar graph) because the auto calculated values are not aligned.
Right now I've got the two relevant elements of the bar graph hard-coded with a specific axis value:
<dvt:y1Axis axisMaxAutoScaled="false" axisMaxValue="100.0"/>
<dvt:y2Axis axisMaxAutoScaled="false" axisMaxValue="100.0"/>
The value I want to use for the Y-axis is calculated and stored in the "axisScale" variable in the above class.
Really at a loss of how to move forward from here.
Would very much appreciate any guidance/direction offered.
Thanks,
Karim
Add a getter for axisScale & regenerate your data control. Add a binding for axisScale to your page & then use that as your maximum value.
The pageDef:
<attributeValues IterBinding="ActivityChartIterator" id="axisScale">
<AttrNames>
<Item Value="axisScale"/>
</AttrNames>
</attributeValues>
The page:
<dvt:y1Axis axisMaxValue="#{bindings.axisScale.attributeValue}" axisMaxAutoScaled="false"/>
<dvt:y2Axis axisMaxValue="#{bindings.axisScale.attributeValue}" axisMaxAutoScaled="false"/>

Moving an image of a TitleAreaDialog to the left

I'm working on a SWT/Jface project based on Java SE, i want to move the image of a TitleAreaDialog to the left. is it possible ? if not is there anyway ?
Thanks,
There is no way to configure it using API, the layout is hard-coded. One way is to hack into the dialog controls and change their layout data, but it is likely easier to implement your own class (using TitleAreaDialog as an example).
If you subclass TitleAreaDialog you have to override createContents(Composite) method, otherwise the TitleAreaDialog will create its own title area by calling createTitleArea(). I suggest that at first you just copy the code from TitleAreaDialog.createContents() and start replacing stuff that you need to be done differently. I don't know exactly what needs to be done without actually doing everything.
You can modify the layout data of the image label as follows:
TitleAreaDialog tad = new TitleAreaDialog(getShell()) {
#Override
protected Control createContents(Composite parent) {
Control control = super.createContents(parent);
Label label = getTitleImageLabel();
FormData data = (FormData) label.getLayoutData();
data.left = new FormAttachment(0, 0);
data.right = null;
return control;
}
};
tad.setTitle("title");
tad.setTitleImage(Activator.imageDescriptorFromPlugin(
Activator.PLUGIN_ID, "image.gif").createImage());
tad.open();

Categories