Monotouch mapkit mkannotation collection gives errors - xamarin.ios

New to monotouch aka xamarin ios. Trying to get a robust mapkit working that can take a number of pins. Experimenting with a basic example that I've cobbled together from a variety of sources that I could find.
Getting a sporadic SIGSEGV error. Seems like some sort of memory error when the pins are clicked to show an alert box which sometimes works and sometimes doesnt.
I'm not sure where I'm going wrong. Is this along the right lines? Here's the code
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.MapKit;
using MonoTouch.CoreLocation;
using System.Collections.Generic;
namespace singleview
{
public partial class singleviewViewController : UIViewController
{
public singleviewViewController () : base ("singleviewViewController", null)
{
}
private LocationService locationService;
private MKMapView mapView;
List<BasicMapAnnotation> pins = new List<BasicMapAnnotation>();
public override void ViewDidLoad()
{
base.ViewDidLoad();
// example of a series of map points
pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.766995, -122.419580), "h", "sub1", "id1"));
pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.776880, -122.418485), "i", "sub2", "id2"));
pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.786775, -122.417390), "j", "sub3", "id3"));
pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.796685, -122.416283), "k", "sub4", "id4"));
var currentLocation = new LocationService().GetCurrentLocation();
var visibleRegion = BuildVisibleRegion(currentLocation);
mapView = BuildMapView(true);
mapView.SetRegion(visibleRegion, true);
this.View.AddSubview(mapView);
// i have a vague idea that this delegate helps to redraw pins as user moves around screen
mapView.Delegate = new MapViewDelegate();
// this pin sometimes has a working callout that activates an alert and sometimes doesnt
var testAnnotationX = new BasicMapAnnotation (new CLLocationCoordinate2D(37.786999,-122.500222),
"made in viewdidload", "outside", "id5");
mapView.AddAnnotation(testAnnotationX);
// this pin collection also sometimes works but most often not
mapView.AddAnnotations(pins.ToArray());
}
private MKMapView BuildMapView(bool showUserLocation)
{
var view = new MKMapView()
{
ShowsUserLocation = showUserLocation,
};
view.Delegate = new MapViewDelegate();
var testAnnotationY = new BasicMapAnnotation (new CLLocationCoordinate2D(37.800000, -122.450777),
"made in buildmapview", "inside", "id6");
view.AddAnnotation(testAnnotationY);
view.SizeToFit();
view.Frame = new RectangleF(0, 0, this.View.Frame.Width, this.View.Frame.Height);
return view;
}
protected class MapViewDelegate : MKMapViewDelegate {
protected string annotationIdentifier = "BasicAnnotation";
UIButton detailButton; // avoid GC
public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
{
if (annotation is MKUserLocation) return null; //ignore user marker
annotationIdentifier = (annotation as BasicMapAnnotation).Id;
// try and dequeue the annotation view
MKAnnotationView annotationView = mapView.DequeueReusableAnnotation(annotationIdentifier);
// if we couldn't dequeue one, create a new one
if (annotationView == null)
{
annotationView = new MKPinAnnotationView(annotation, annotationIdentifier);
//annotationView.RightCalloutAccessoryView = new UIButton(UIButtonType.DetailDisclosure); //- not required as its at bottom??
// configure our annotation view properties
annotationView.CanShowCallout = true;
(annotationView as MKPinAnnotationView).AnimatesDrop = true;
(annotationView as MKPinAnnotationView).PinColor = MKPinAnnotationColor.Green;
annotationView.Selected = true;
// you can add an accessory view; in this case, a button on the right and an image on the left
detailButton = UIButton.FromType(UIButtonType.DetailDisclosure);
detailButton.TouchUpInside += (s, e) => {
Console.WriteLine ("Clicked");
new UIAlertView("Annotation Clicked", "You clicked on " +
(annotation as MKAnnotation).Coordinate.Latitude.ToString() + ", " +
(annotation as MKAnnotation).Coordinate.Longitude.ToString() , null, "OK", null).Show();
};
annotationView.RightCalloutAccessoryView = detailButton;
}
else // if we did dequeue one for reuse, assign the annotation to it
annotationView.Annotation = annotation;
/*
// configure our annotation view properties
annotationView.CanShowCallout = true;
(annotationView as MKPinAnnotationView).AnimatesDrop = true;
(annotationView as MKPinAnnotationView).PinColor = MKPinAnnotationColor.Green;
annotationView.Selected = true;
*/
// fix and uncomment
//annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromBundle("29_icon.png"));
return annotationView;
}
// as an optimization, you should override this method to add or remove annotations as the
// map zooms in or out.
public override void RegionChanged (MKMapView mapView, bool animated) {}
}
private MKCoordinateRegion BuildVisibleRegion(CLLocationCoordinate2D currentLocation)
{
var span = new MKCoordinateSpan(0.2,0.2);
var region = new MKCoordinateRegion(currentLocation,span);
return region;
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
}
}
public class BasicMapAnnotation : MKAnnotation{
public override CLLocationCoordinate2D Coordinate {get;set;}
string title, subtitle;
public override string Title { get{ return title; }}
public override string Subtitle { get{ return subtitle; }}
public string Id {get ;set;}
public BasicMapAnnotation (CLLocationCoordinate2D coordinate, string title, string subtitle, string id) {
this.Coordinate = coordinate;
this.title = title;
this.subtitle = subtitle;
this.Id = id;
}
}
public class LocationService
{
private CLLocationManager locationManager;
public LocationService()
{
locationManager = new CLLocationManager();
}
public CLLocationCoordinate2D GetCurrentLocation()
{
//dirty for now just to get some info.
locationManager.StartUpdatingLocation();
while(locationManager.Location == null);
locationManager.StopUpdatingLocation();
//return new CLLocationCoordinate2D ( 37.786995, -122.419280);
return locationManager.Location.Coordinate;
}
}
}
Error:
Stacktrace:
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
at singleview.Application.Main (string[]) [0x00000] in .../singleview/Main.cs:17
at (wrapper runtime-invoke) .runtime_invoke_void_object (object,intptr,intptr,intptr)
Native stacktrace:
0 singleview 0x00091eac mono_handle_native_sigsegv + 284
1 singleview 0x00005788 mono_sigsegv_signal_handler + 248
2 libsystem_c.dylib 0x938658cb _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 UIKit 0x0274f258 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
5 UIKit 0x02810021 -[UIControl sendAction:to:forEvent:] + 66
6 UIKit 0x0281057f -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 578
7 UIKit 0x0280f6e8 -[UIControl touchesEnded:withEvent:] + 546
8 UIKit 0x0277ecef -[UIWindow _sendTouchesForEvent:] + 846
9 UIKit 0x0277ef02 -[UIWindow sendEvent:] + 273
10 UIKit 0x0275cd4a -[UIApplication sendEvent:] + 436
11 UIKit 0x0274e698 _UIApplicationHandleEvent + 9874
12 GraphicsServices 0x04d40df9 _PurpleEventCallback + 339
13 GraphicsServices 0x04d40ad0 PurpleEventCallback + 46
14 CoreFoundation 0x012bfbf5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
15 CoreFoundation 0x012bf962 __CFRunLoopDoSource1 + 146
16 CoreFoundation 0x012f0bb6 __CFRunLoopRun + 2118
17 CoreFoundation 0x012eff44 CFRunLoopRunSpecific + 276
18 CoreFoundation 0x012efe1b CFRunLoopRunInMode + 123
19 GraphicsServices 0x04d3f7e3 GSEventRunModal + 88
20 GraphicsServices 0x04d3f668 GSEventRun + 104
21 UIKit 0x0274bffc UIApplicationMain + 1211
22 ??? 0x0f4d71ad 0x0 + 256733613
23 ??? 0x0f4d4e40 0x0 + 256724544
24 ??? 0x0f4d4a48 0x0 + 256723528
25 ??? 0x0f4d4b9e 0x0 + 256723870
26 singleview 0x00009b52 mono_jit_runtime_invoke + 722
27 singleview 0x0016d02e mono_runtime_invoke + 126
28 singleview 0x00171224 mono_runtime_exec_main + 420
29 singleview 0x00176615 mono_runtime_run_main + 725
30 singleview 0x000671e5 mono_jit_exec + 149
31 singleview 0x00204fd4 main + 1988
32 singleview 0x00002b75 start + 53
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================

Looks like the good old GC Error.
Take a look at the Monotouch-Samples App exactly this Class and Line:
https://github.com/xamarin/monotouch-samples/blob/master/MapCallouts/MainViewController.cs#L108
You need to store all the Pinviews within some Collection, so the Garbage Collection doesn't try to collect them.

What about the 'var testAnnotationX'? You might need to move that as well.

Related

How to manage several Serial messages in processing

I am reading the UID of my RFID card and storing it in a variable called myUID.
After that I am authorizing to the card with the factory key and read block number 4 (which has been written to earlier) and store it in a string readBlock.
On the Arduino, I print out the variables onto the serial interface like so.
Serial.println(myUID);
Serial.println(readBlock);
On the client side, I use a Java program that reads in serial data. My program uses the Processing Library.
Serial mySerial;
PrintWriter output;
void setup() {
output = createWriter( "data.txt" );
mySerial = new Serial( this, Serial.list()[0], 9600 );
mySerial.bufferUntil('\n');
}
void draw(){
while (mySerial.available() > 0) {
String inBuffer = mySerial.readString();
if (inBuffer != null)
output.println(inBuffer);
}
}
void keyPressed() { // Press a key to save the data
output.flush(); // Write the remaining data
output.close(); // Finish the file
exit(); // Stop the program
}
Now my data.txt is expected to look like
xxx xxx xxx xxx (uid of card)
00 00 00 00 00 00 00 00 ... (read block from card)
but looks like
237 63 58 1
07
37 37 95
37
97 98 50 54 37 5
4 55 102 55 52
45 98
I have tried several things like readStringUntil('\n'); in the Processing Library but without success.
For everyone interested, I have fixed the problem myself with many hours of searching Google, so maybe this will help someone in the future:
I could fix it with this code:
import processing.serial.*;
int count = 0;
String input = "";
String fileName = dataPath("SET FILEPATH HERE");
Serial mySerial;
import java.io.*;
void setup() {
mySerial = new Serial(this, Serial.list()[0], 9600);
mySerial.bufferUntil('\n');
File f = new File(fileName);
if (f.exists()) {
f.delete();
}
}
void draw(){}
// listen to serial events happening
void serialEvent(Serial mySerial){
input = mySerial.readStringUntil('\n');
write(input, count);
count++;
}
// function for writing the data to the file
void write(String inputString, int counter) {
// should new data be appended or replace any old text in the file?
boolean append = false;
// just for my purpose, because I have got two lines of serial which need to get written to the file
//(Line 1: UID of card, Line 2: Read block of card)
if(counter < 2){
append = true;
}
else{
count = 0;
}
try {
File file = new File("D:/xampp/htdocs/pizza/src/rfid/data.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file, append);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
pw.write(inputString + '\n');
pw.close();
}
catch(IOException ioe) {
System.out.println("Exception ");
ioe.printStackTrace();
}
}

Hazelcast IMap LRU Eviction Policy always evicting the latest entry

We were exploring the different eviction policy options and found out that the LRU Eviction policy is evicting the newly added entry instead of Least Recently Used entry. It behaves the same way for LFU option as well.
Ideally, the first entry should get evicted first before the second or third gets evicted.
Is this a bug in Hazelcast or am I missing any option/configuration?
Hazelcast Version - 3.6.2
Here is the code sample to replicate the issue(Run with -Xmx512m):
import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MaxSizeConfig;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.map.listener.EntryEvictedListener;
import java.util.concurrent.ConcurrentHashMap;
public class HazelcastMaxSizeTest {
private static final String GROUP_NAME = "TEST";
private static final String MAP_NAME = "test";
private static final ConcurrentHashMap<Long, byte[]> theDataMap = new ConcurrentHashMap<Long, byte[]>();
private static MaxSizeConfig USED_HEAP_PERCENTAGE = new MaxSizeConfig(5, MaxSizeConfig.MaxSizePolicy.USED_HEAP_PERCENTAGE);
private static MaxSizeConfig USED_HEAP_SIZE = new MaxSizeConfig(128, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE);
private static MaxSizeConfig FREE_HEAP_SIZE = new MaxSizeConfig(128, MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE);
private static MaxSizeConfig FREE_HEAP_PERCENTAGE = new MaxSizeConfig(30, MaxSizeConfig.MaxSizePolicy.FREE_HEAP_PERCENTAGE);
public static void main(String[] args) throws Exception {
boolean storeOutSideHazelcast = true;
HazelcastInstance instance = startHazelcast("hazelcast1", FREE_HEAP_PERCENTAGE);
System.out.println("started " + instance.getName());
IMap<Long, byte[]> map = createMap(instance, MAP_NAME, storeOutSideHazelcast);
System.out.println("map size: " + map.size());
instance.shutdown();
System.exit(0);
}
private static HazelcastInstance startHazelcast(String instanceName, MaxSizeConfig maxSizeConfig) {
MapConfig mapConfig = new MapConfig(MAP_NAME);
mapConfig.setMaxSizeConfig(maxSizeConfig);
mapConfig.setStatisticsEnabled(true);
mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
mapConfig.setEvictionPercentage(10);
mapConfig.setMinEvictionCheckMillis(0L);
mapConfig.setBackupCount(0);
mapConfig.setTimeToLiveSeconds(600);
Config config = new Config(instanceName);
config.addMapConfig(mapConfig);
config.getManagementCenterConfig().setEnabled(true);
config.getManagementCenterConfig().setUrl("http://localhost:8080/mancenter-3.6.2.war");
config.getGroupConfig().setName(GROUP_NAME).setPassword(GROUP_NAME);
return Hazelcast.getOrCreateHazelcastInstance(config);
}
private static IMap<Long, byte[]> createMap(HazelcastInstance instance,
String mapname
, boolean storeOutsideHZMap ) {
IMap<Long, byte[]> map = instance.getMap(mapname);
map.addEntryListener(new EntryEvictedListener<Long, byte[]>() {
#Override
public void entryEvicted(EntryEvent<Long, byte[]> event) {
System.out.println("Evicted Key" + ": " + event.getKey());
theDataMap.remove(event.getKey());
}
}, false);
for (long i = 1; i <= 1000; i++) {
if(storeOutsideHZMap == true) {
theDataMap.put(i, new byte[50 * 50000]);
map.set(i, new byte[10]);
System.out.println("Adding Key " + ": " + i);
map.get(i);
}else {
map.set(i, new byte[50*50000]);
}
if (i % 100 == 0) {
// System.out.println("set " + map.getName() + ": " + i);
try {
Thread.sleep(5000l);
}catch (Exception e){}
}
}
return map;
}
}
Sample Output:
Adding Key : 147
Evicted Key: 147
Adding Key : 148
Evicted Key: 148
Adding Key : 149
Evicted Key: 149
Adding Key : 150
Evicted Key: 150
Adding Key : 151
Evicted Key: 151
Adding Key : 152
Evicted Key: 152
Adding Key : 153
Evicted Key: 153
Adding Key : 154
Evicted Key: 154
Adding Key : 155
Evicted Key: 155
Adding Key : 156
Evicted Key: 156
Adding Key : 157
Evicted Key: 157

Terminating app due to uncaught exception 'NSInvalidArgumentException while trying to save the core data

I have a problem when trying to save my record to core data. The idea is to save a simple student information into the core data database. You can see the detail below.
My Entity class:
import Foundation
import CoreData
class Student: NSManagedObject {
#NSManaged var id: String
#NSManaged var firstname: String
#NSManaged var lastname: String
#NSManaged var age: NSNumber
#NSManaged var email: String
}
The code is :
import UIKit
import CoreData
class AddControllerViewController: UIViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
#IBOutlet var id: UITextField!
#IBOutlet var firstname: UITextField!
#IBOutlet var lastname: UITextField!
#IBOutlet var age: UITextField!
#IBOutlet var email: UITextField!
#IBAction func save(sender: AnyObject) {
let entityDescripition = NSEntityDescription.entityForName("Student", inManagedObjectContext: managedObjectContext!)
let student = Student(entity: entityDescripition!, insertIntoManagedObjectContext: managedObjectContext)
student.id = id.text
student.firstname = firstname.text
student.lastname = lastname.text
student.age = age.text.toInt()!
student.email = email.text
managedObjectContext?.save(nil)
navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
and the error message i was getting :
2014-10-14 16:31:42.098 Registration[3829:119352] -[Registration.Student setId:]: unrecognized selector sent to instance 0x7fc667a77070
2014-10-14 16:31:42.105 Registration[3829:119352] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Registration.Student setId:]: unrecognized selector sent to instance 0x7fc667a77070'
Has anybody had similar error before and found the way to fix it ?
When i put the break point i got these :
2014-10-14 21:52:49.227 Registration[513:9236] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Registration.Student setId:]: unrecognized selector sent to instance 0x7fe441c3d100'
*** First throw call stack:
(
0 CoreFoundation 0x00000001062593f5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000107d87bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010626050d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001061b87fc ___forwarding___ + 988
4 CoreFoundation 0x00000001061b8398 _CF_forwarding_prep_0 + 120
5 Registration 0x0000000105cbc887 _TFC12Registration27AddControllerViewController4savefS0_FPSs9AnyObject_T_ + 935
6 Registration 0x0000000105cbcd02 _TToFC12Registration27AddControllerViewController4savefS0_FPSs9AnyObject_T_ + 66
7 UIKit 0x0000000106ae49ee -[UIApplication sendAction:to:from:forEvent:] + 75
8 UIKit 0x0000000106ae49ee -[UIApplication sendAction:to:from:forEvent:] + 75
9 UIKit 0x0000000106beabd0 -[UIControl _sendActionsForEvents:withEvent:] + 467
10 UIKit 0x0000000106be9f9f -[UIControl touchesEnded:withEvent:] + 522
11 UIKit 0x0000000106b2a3b8 -[UIWindow _sendTouchesForEvent:] + 735
12 UIKit 0x0000000106b2ace3 -[UIWindow sendEvent:] + 683
13 UIKit 0x0000000106af7ae1 -[UIApplication sendEvent:] + 246
14 UIKit 0x0000000106b04bad _UIApplicationHandleEventFromQueueEvent + 17370
15 UIKit 0x0000000106ae0233 _UIApplicationHandleEventQueue + 1961
16 CoreFoundation 0x000000010618ead1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17 CoreFoundation 0x000000010618499d __CFRunLoopDoSources0 + 269
18 CoreFoundation 0x0000000106183fd4 __CFRunLoopRun + 868
19 CoreFoundation 0x0000000106183a06 CFRunLoopRunSpecific + 470
20 GraphicsServices 0x000000010a3489f0 GSEventRunModal + 161
21 UIKit 0x0000000106ae3550 UIApplicationMain + 1282
22 Registration 0x0000000105cc070e top_level_code + 78
23 Registration 0x0000000105cc074a main + 42
24 libdyld.dylib 0x0000000108561145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Wrong results when trying to get sizes of a pane with css-formattings

I came across a strange behaviour of JavaFX when i tried to obtain the bordersizes (bounds) of a pane that has some css-effects//formattings applied to it. In my application i have to lookup the exact sizes of different objects in order to connect them with lines (imagine some sort of UML-diagramm editor, the start and endpoints of the lines are the border coordinates of the objects).
Now to my problem: whenever i try to get the bordersizes of an object in the same method where this object is put on the scene graph, the result does not include any css attributes like padding, bordersize, strokes and so on. The exact result gets returned if the object already exists on the scene graph before i lookup the size. It seems to be that JavaFX has to wait for one rendering pass (16,7ms) to actually update the real bounds and sizes on an object. Is there any way to get the size of an object (especially those which extend Pane) in the same method as it is created? I don't really like the workaround with waiting for 16,7ms, because it creates some unwanted behaviour in my application.
The following code shows the problem. The size when creating the pane containing the rectangle does not equal the size when pressing the "show size" button.
public class SzenarioView extends GridPane
{
private Group paintingLayer;
public SzenarioView()
{
super();
paintingLayer = new Group();
paintingLayer.getStylesheets().add(TestStarter.class.getResource("ReprBox.css").toString());
Rectangle r1 = new Rectangle(0, 0, 1000, 1000);
r1.setFill(Color.AZURE);
paintingLayer.getChildren().add(r1);
Button b1 = new Button("Show Size");
b1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
for(Node n : paintingLayer.getChildren())
{
System.out.println("Border...");
System.out.println(getNodeBorderCoords(n, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(n, BorderTypes.RIGHT)[1]);
System.out.println("End Border");
}
}
});
Button b2 = new Button("Add CCSBTN");
b2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
BorderPane bp = new BorderPane();
bp.getStylesheets().add(TestStarter.class.getResource("ReprBox.css").toString());
Rectangle rcss = new Rectangle(50, 50);
bp.setTop(rcss);
bp.getStyleClass().add("my-box");
setObjectOnScreen(bp, 100, 100);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
}
});
this.add(b1, 0, 0);
this.add(b2, 1, 0);
this.add(paintingLayer, 1, 1);
this.setMaxHeight(500);
this.setMaxWidth(700);
this.setHgap(10);
this.setVgap(10);
this.setPadding(new Insets(10, 10, 10, 10));
}
public void setObjectOnScreen(Node obj, double toX, double toY)
{
obj.setLayoutX(toX);
obj.setLayoutY(toY);
paintingLayer.getChildren().add(obj);
}
public double[] getNodeBorderCoords(Node n, BorderTypes type)
{
double x = 0;
double y = 0;
double bx = n.getBoundsInLocal().getWidth();
double by = n.getBoundsInLocal().getHeight();
switch (type)
{
case LEFT:
x = n.getLayoutX();
y = n.getLayoutY() + by / 2;
break;
case RIGHT:
x = n.getLayoutX() + bx ;
y = n.getLayoutY() + by / 2;
break;
case TOP:
x = n.getLayoutX() + bx / 2;
y = n.getLayoutY();
break;
case BOTTOM:
x = n.getLayoutX() + bx / 2;
y = n.getLayoutY() + by;
break;
}
double[] ret =
{ x, y, };
return ret;
}
}
The CSS-File
#CHARSET "ISO-8859-1";
.my-box {
-fx-border-color: rgb(255, 0, 0);
-fx-border-radius: 2;
-fx-padding: 1 1 1 1;
-fx-border-width: 5 5 5 5;
}
By the way, it doesn't matter if use getBoundsInLocal() or getBoundsInParent() .
UPDATE
Here are two workarounds that can be used:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
}
});
}
});
t.start();
But delaying the call might cause some strange behaviour like i stated in my post. But i found another "solution" recently.
bp.snapshot(new SnapshotParameters(), new WritableImage(5, 5));
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
The snapshot() method applies all css effects (and all other layout work) on the node. After that, the returned values of the borders are correct.
There are 2 approaches:
You can use binding instead of static size call. It gives benefits of additional support for update after resize but adds a bit of listeners handling burden on FX enging.
Wrapping size reading logic into Platform.runLater() will put it later into event queue and should address premature size access issue.

Converting flat data structure into hierarchy Object using c#

I have the following Flat Data Structure.
ParentAttributeId AttributeId List
----------------- ----------- ------
NULL 29 TestcaseCollection
29 30 EnclosureLeakageDielectricStrengthTest
30 31 DeviceID
30 32 ScannerOneLowChannel
30 33 ScannerTwoLowChannel
29 34 EnclosureLeakageLeakageCurrentTest
34 35 DeviceID
34 36 ScannerOneLowChannel
34 37 ScannerTwoLowChannel
29 38 PatientCircuitLeakageTest
38 39 DeviceID
38 40 ScannerOneLowChannel
38 41 ScannerTwoLowChannel
29 42 SIPSOPDielectricStrengthTest
42 44 ScannerOneHighChannel
42 45 ScannerOneLowChannel
42 46 ScannerTwoHighChannel
42 47 ScannerTwoLowChannel
29 48 SIPSOPLeakageCurrentTest
48 49 ScannerOneHighChannel
48 50 ScannerOneLowChannel
48 51 ScannerTwoHighChannel
48 52 ScannerTwoLowChannel
I need to convert above flat data structure into a hierarchy Object structure like below. So my Object looks like the "List" Column above. I am using SQL Stored Proc to get the above data. I am using C#.
Object hierarchy
29
|
30
| 31
| 32
| 33
|
34
| 35
| 36
|37
38
Any help would be greatly appreciated.
Regards
Niju
You could try something like this:
1) Create a node class
class Node
{
public int ParentId { get; private set; }
public int Id { get; private set; }
public string Label { get; private set; }
public Node Parent { get; set; }
public List<Node> Children { get; } = new List<Node>();
public Node(int parentId, int id, string lable)
{
ParentId = parentId;
Id = id;
Label = lable;
}
public void AddChild(Node child)
{
child.Parent = this;
Children.Add(child);
}
public void Trace(int indent = 1)
{
Enumerable.Range(0, indent).ToList().ForEach(i => Console.Write(" - "));
Console.WriteLine(Label);
Children.ForEach(c => c.Trace(indent + 1));
}
}
2) Create node objects from you flat data and add them to a dictionary
var data = new List<DataRow>() {
new DataRow { ParentId = 0, Id = 1, Label = "parent" },
new DataRow { ParentId = 1, Id = 2, Label = "child 1" },
new DataRow { ParentId = 1, Id = 3, Label = "child 2" },
new DataRow { ParentId = 2, Id = 4, Label = "grand child 1" },
new DataRow { ParentId = 2, Id = 5, Label = "grand child 2" }
};
Dictionary<int, Node> nodes = data.ToDictionary(d => d.Id, d => new Node(d.ParentId, d.Id, d.Label));
3) Build the hierarchy by looping through all nodes calling AddChild on the parent
foreach (var node in nodes.Skip(1))
nodes[node.Value.ParentId].AddChild(node.Value);
If you call Trace() on the top node, the output will look like this:
- parent
- - child 1
- - - grand child 1
- - - grand child 2
- - child 2
Have you looked at AutoMapper?
Not sure this is what you need but it's what I use to often convert from one format to an object model.
Another alternative might be to use LINQ to query the data you have and to create the model for you.
I think you can say something like, and this is untested;
select from dataList select new {....
where new would be the new object you are creating.
However, i think maybe the brute force approach of iterating through your list might still be the way.
edit
this might help.

Resources