How to move the graph viewport when adding time-based items to a series at runtime? - android-graphview

I'm trying to create a graph with displays the last n seconds of data arriving by bluetooth. I want to add to the series from within a timer by adding a DataPoint with a Date as X value. All I get is a white screen. I think that the problem lies with the values used in ´graph.getViewport().setMinX`.
What value should I set for minX and maxX if I want to display the last n seconds of data?
public class MainActivity extends ActionBarActivity {
private Handler mHandler;
private GraphView graph;
LineGraphSeries<DataPoint> serFl = new LineGraphSeries<DataPoint>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initGraph();
mHandler = new Handler();
startRepeatingTask();
}
private void initGraph() {
try {
graph = (GraphView) findViewById(R.id.graph);
serFl.setColor(Color.BLUE);
graph.addSeries(serFl);
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(System.currentTimeMillis() - 10000);
graph.getViewport().setMaxX(System.currentTimeMillis() + 1000);
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(0);
graph.getViewport().setMaxY(20);
final SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
graph.getGridLabelRenderer().setLabelFormatter(
new DefaultLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
Date d = new Date((long) value);
return sdf.format(d);
} else {
// show currency for y values
return super.formatLabel(value, isValueX);
}
}
});
} catch (Exception x) {
System.err.println(x);
}
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
updateStatus();
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
protected void updateStatus() {
DataMessage msg = source.fetch();
long d = msg.getTimestamp();
serFl.appendData(new DataPoint(d, msg.getFl()), true,
settings.getMaxSeriesSize());
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}

You did not
graph.onDataChanged(false, false);
after setting the graph.getViewport().setMaxY(20);.
This helped in my case.

Related

Camera in Android app

I am creating an app which required to perform from API 15 to API 23 using camera so what should be the best way to implement camera as camera class is deprecated in API 21 and also android.hardware.camera2 not able to implement on lower version then API 21.
The below code is something I have taken out of one of my projects, it has had a lot of stuff ripped out for the purpose of putting it on here so you will have to edit it for your needs. It uses the original camera api which is back compatible for your api needs.
public class RecordGameKam extends Fragment
implements TextureView.SurfaceTextureListener, View.OnClickListener {
private final static String TAG = "CameraRecordTexture";
private Camera mCamera;
private TextureView mTextureView;
int numberOfCameras;
int defaultCameraId;
private boolean isRecording = false;
protected MediaRecorder mediaRecorder;
#SuppressWarnings("ConstantConditions")
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
View rootView = new RelativeLayout(getActivity());
mTextureView = new TextureView(getActivity());
mTextureView.setSurfaceTextureListener(this);
//View parameters-----------------------------------------------------------------------
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
rootView.setLayoutParams(params);
((ViewGroup) rootView).addView(mTextureView);
return rootView;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
// Find the total number of cameras available
numberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the default camera
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}
try {
if (mCamera != null) {
//final Camera.Size previewSize = onMeasure();
//Camera.Size recorderSize = previewSize;
final Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(720, 480);
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
startContinuousAutoFocus();
}
} catch (IOException ioe) {
// Something bad happened
mCamera.release();
mCamera = null;
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
try {
if (getActivity().getActionBar() != null) {
getActivity().getActionBar().show();
}
} catch (Exception e) {
e.printStackTrace();
}
releaseMediaRecorder();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
}
private boolean setMediaRecorder() throws IllegalStateException {
try {
//Create a new instance of MediaRecorder.
mediaRecorder = new MediaRecorder();
//Unlock and set camera to Media recorder
mCamera.unlock();
mediaRecorder.setCamera(mCamera);
//Configure audio/video input
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
CamcorderProfile profile = null;
if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
}
if (profile != null) {
mediaRecorder.setProfile(profile);
}
//Change oritentation
mediaRecorder.setOrientationHint(90 - 180 + 360);
mediaRecorder.setOutputFile(getFilename());
} catch (Exception e) {
e.printStackTrace();
}
//Attempt to prepare the configuration and record video.
try {
button.setBackgroundResource(R.drawable.camera_pressed);
mediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
mediaRecorder.release();
return false;
}
return true;
}
boolean startContinuousAutoFocus() {
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
assert focusModes != null;
String CAF_PICTURE = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
CAF_VIDEO = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
supportedMode = focusModes
.contains(CAF_PICTURE) ? CAF_PICTURE : focusModes
.contains(CAF_VIDEO) ? CAF_VIDEO : "";
if (!supportedMode.equals("")) {
params.setFocusMode(supportedMode);
mCamera.setParameters(params);
return true;
}
return false;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
enter code here

Progress Dialog on Rajawali Vuforia example

It is possible to show progress dialog when loading the .obj model. I tried to call the ProgressDialog in RajawaliVuforiaExampleRenderer.java but it said "Can't create handler inside thread that has not called Looper.prepare()"
I have pasted part of the code here:
protected void initScene() {
mLight = new DirectionalLight(.1f, 0, -1.0f);
mLight.setColor(1.0f, 0, 0);
mLight.setPower(1);
getCurrentScene().addLight(mLight);
LoaderOBJ objParser = new LoaderOBJ(mContext.getResources(),
mTextureManager, R.raw.wall_obj);
try {
// Load model
objParser.parse();
wall = objParser.getParsedObject();
addChild(wall);
} catch (Exception e) {
e.printStackTrace();
}
}
EDITED:
I have read the comment from Abhishek Agarwal and updated the code for Renderer part, now i having problem on calling the ProgressDialog when loading the model, here is my code for the UI thread.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// receive file path
String filePath = this.getIntent().getStringExtra("FullFilePath");
Log.i(filePath, "FullFilePath:" + filePath);
waitDialog = ProgressDialog.show(this, "", "Loading", true);
waitDialog.show();
new ModelLoader().execute();
}
#Override
protected void setupTracker() {
int result = initTracker(TRACKER_TYPE_MARKER);
if (result == 1) {
result = initTracker(TRACKER_TYPE_IMAGE);
if (result == 1) {
super.setupTracker();
} else {RajLog.e("Couldn't initialize image tracker.");
}
} else {
RajLog.e("Couldn't initialize marker tracker.");
}}
protected void initApplicationAR() {
super.initApplicationAR();
createImageMarker("marker.xml");
}
protected void initRajawali() {
super.initRajawali();
mRenderer = new ModelRenderer(this);
mRenderer.setSurfaceView(mSurfaceView);
super.setRenderer(mRenderer);
mUILayout = this;
mUILayout.setContentView(mLayout, new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
private class ModelLoader extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
startVuforia();
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
waitDialog.dismiss();
}
}
Progress Dialog can be shown on the UIThread. So show progress dialog on the main thread not under GLThread
You can use Handler to be on threadUI :
`private Handler mHandler = new Handler();
...
mHandler.post(new Runnable() {
#Override
public void run() {
view_progressBar.setProgress(val);
}
});`

JList update freezes display but not JFrame setTitle

If I update a JList with a long number of html formatted items then the controls stop responding and indicators won't update. This makes sense, the event thread is busy. The title can still be set though. Why is this?
Here's some (long) code demonstrating this:
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
public class JListTest extends JFrame {
class TestListModel extends AbstractListModel<String> {
private static final long serialVersionUID = JListTest.serialVersionUID;
private boolean useHtml;
private String[] formattedList = new String[] {};
public int getSize() {
return formattedList.length;
}
public String getElementAt(int index) {
return formattedList[index];
}
public void setUseHtml(boolean useHtml) {
this.useHtml = useHtml;
}
public String getNewListItem() {
if (useHtml) {
return "<html><div style='padding:2px"
+ ";background-color:#EDF5F4;color:black'><div style='padding:2px;font-weight:500;'>"
+ "Item " + (100 * Math.random())
+ "</div>"
+ "This will change!"
+ "</div></html>";
} else {
return "Item " + (100 * Math.random());
}
}
public void updateItems() {
formattedList = new String[] {"<html><h1>Loading!</h1></html>"};
fireContentsChanged(this, 0, 1);
Thread buildItems = new Thread() {
#Override
public void run() {
final String[] tempList = new String[3000];
for (int i=0; i<tempList.length; i++) {
tempList[i] = getNewListItem();
}
// Just show the string bashing's done
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
formattedList = new String[] {"<html><h1>Updating!</h1></html>"};
fireContentsChanged(TestListModel.this, 0, 1);
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update
SwingUtilities.invokeLater(new Runnable() {
public void run() {
formattedList = tempList;
fireContentsChanged(TestListModel.this, 0, formattedList.length);
}
});
}
};
buildItems.start();
}
}
protected static final long serialVersionUID = 1L;
public JListTest() {
JPanel controlPanel = new JPanel();
JButton updaterControl = new JButton("Add 3000");
final JCheckBox useHtmlControl = new JCheckBox("Use HTML");
final TestListModel model = new TestListModel();
JList<String> list = new JList<String>(model);
JScrollPane scrollPane = new JScrollPane(list);
final JLabel durationIndicator = new JLabel("0");
controlPanel.add(useHtmlControl, BorderLayout.WEST);
controlPanel.add(updaterControl, BorderLayout.EAST);
getContentPane().add(controlPanel, BorderLayout.PAGE_START);
getContentPane().add(scrollPane, BorderLayout.CENTER);
getContentPane().add(durationIndicator, BorderLayout.PAGE_END);
useHtmlControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setUseHtml(useHtmlControl.isSelected());
}
});
useHtmlControl.setSelected(false);
updaterControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.updateItems();
}
});
Timer counter = new Timer();
counter.schedule(new TimerTask() {
#Override
public void run() {
String previousCounter = durationIndicator.getText();
String newCounter = Integer.toString(
Integer.parseInt(previousCounter) + 1);
durationIndicator.setText(newCounter);
setTitle(newCounter);
}
}, 0, 100);
}
public static void main(String args[]) {
JListTest jlt = new JListTest();
jlt.pack();
jlt.setSize(300, 300);
jlt.setVisible( true );
}
}
The answer is pretty obvious - because Window title is not a Swing component, it's OS native entity.
So changes don't have to go through Swing Event Queue, but go to XDecoratedPeer.updateWMName directly in case of Unix and to some other class in other OSes.
The more interesting question would be how to avoid that UI blocking, but I don't think that's possible with just Swing, you'll have to implement some lazy loading, or rendering in batches.

Refresh ListView when Device receives GCM IntentService Message

My app is able to receive messages from GCM and saves the messages to the SQLlite database on the phone. The messages are viewable in a activity that has a listview.
In the code below, the onPause() function refreshes the listView. This is not a good implementation because it only works if the activity is not displayed at the time of the update. If the activity is displayed at the time of an update, the list is static and does not update.
Questions:
How to I update the listview when the activity is being displayed? Or is there a way to use a background service to update the adapter, so that whenever the activity is displayed, it always shows the newest data.
is this kind of functionality currently not possible with android and I'll need to implement something else like 'pull-to-refresh'?
refreshing listview in OnResume() crashes the application, and shows a null pointer exception.
Activity:
public class NotesView extends Activity implements OnItemClickListener {
ListView listView;
NoteAdapter objAdapter;
NotificationsDatabase db = new NotificationsDatabase(this);
List<Notes> listAlerts;
String note;
String time;
TextView noteView;
TextView timeView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
new MyTask().execute();
}
// My AsyncTask start...
class MyTask extends AsyncTask<Void, Void, List<Notes>> {
ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NotesView.this);
pDialog.setMessage("Loading...");
pDialog.setCancelable(false);
pDialog.show();
if (isCancelled()) {
this.cancel(true);
}
}
#Override
protected List<Notes> doInBackground(Void... params) {
db.open();
listAlerts = db.getData();
if (isCancelled()) {
this.cancel(true);
}
return null;
}
protected void onPostExecute(List<Notes> alerts) {
if (null != pDialog && pDialog.isShowing()) {
pDialog.dismiss();
}
db.close();
setAdapterToListview();
}
}// end myTask
public void setAdapterToListview() {
objAdapter = new NoteAdapter(NotesView.this, R.layout.row_notes, listAlerts);
objAdapter.sortByNoteDesc();
objAdapter.notifyDataSetChanged();
listView.setAdapter(objAdapter);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
Intent intent = new Intent(
NotesView.this.getApplicationContext(),
TabBarExample.class);
intent.putExtra("goToTab", "Alerts");
startActivity(intent);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void onItemClick(AdapterView<?> parent, View viewDel, int position,
long id) {
for (int i = 0; i < 1; i++) {
Notes item = listAlerts.get(position);
int ids = item.getId();
note = item.getNote();
time = item.getTimeStamp();
}
System.out.println(note + " " + time);
//
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setAdapter(null);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
new MyTask().execute();
}
#Override
protected void onDestroy() {
}
}
Code snippets From GCMIntentService
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
//String message = getString(R.string.gcm_message);
System.out.println("onMessage: ");
Bundle extras = intent.getExtras();
String message = extras.getString("message");
String event_id_from_server = extras.getString("server_id");
// displayMessage(context, message);
generateNotification(context, message);
saveMsg(message);
System.out.println("server id is " + event_id_from_server);
if (event_id_from_server != null) {
updateLocalDatabase(event_id_from_server);
}
}
public void saveMsg(String msg) {
boolean worked = true;
try {
NotificationsDatabase entry = new NotificationsDatabase(GCMIntentService.this);
entry.open();
java.util.Date date = new java.util.Date();
Timestamp x = new Timestamp(date.getTime());
String timeStamp = x.toLocaleString();
entry.createEntry(msg, timeStamp);
entry.close();
//update adapter service
} catch (Exception e) {
worked = false;
String error = e.toString();
System.out.println(error);
} finally {
if (worked) {
}
}
}
I cleaned up your code a little bit. Basically all the view assignments should be done once in onCreate, while the loading of the data should be done in onResume(). See if this helps:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setAdapter(null);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
}
#Override
protected void onResume() {
super.onResume();
new MyTask().execute();
}
#Override
protected void onPause() {
super.onPause();
}

Problem with GWT connector in a straight ended connection

I am trying to make a straight ended connection between widgets.But when I am doing so, the orientation of my connector is coming wrong.Its always coming parallel to the required one.Also , it is independent of the connecting widgets i.e when I move my widget, my connector does not move.Snippet of my code is given as :
Link to snapshot of the problem: http://goo.gl/JUEmJ
public class DragNDropPage {
SyncCurrentUser cu = SyncCurrentUser.getUser();
private AbsolutePanel area = new AbsolutePanel();
HorizontalPanel toolsPanel = new HorizontalPanel();
AbsolutePanel canvas = new AbsolutePanel();
DragController toolboxDragController;
Label startLabel = new Label("START");
Label stopLabel = new Label("STOP");
Label activityLabel = new Label("ACTIVITY");
Label processLabel = new Label("PROCESS");
Button stopDrag = new Button("Done Dragging");
Button saveButton = new Button("Save");
PickupDragController dragController = new PickupDragController(area, true);
AbsolutePositionDropController dropController = new AbsolutePositionDropController(area);
private List<Widget> selected = new ArrayList<Widget>();
private List<Widget> onCanvas = new ArrayList<Widget>();
private List<Connection> connections = new ArrayList<Connection>();
private CActivity[] aItems;
private CProcess[] pItems;
MyHandler handler = new MyHandler();
int mouseX,mouseY;
String style;
public DragNDropPage() {
toolboxDragController = new ToolboxDragController(dropController, dragController);
RootPanel.get("rightbar").add(area);
area.setSize("575px", "461px");
area.add(toolsPanel);
toolsPanel.setSize("575px", "37px");
toolsPanel.add(startLabel);
startLabel.setSize("76px", "37px");
toolboxDragController.makeDraggable(startLabel);
toolsPanel.add(stopLabel);
stopLabel.setSize("66px", "37px");
toolboxDragController.makeDraggable(stopLabel);
toolsPanel.add(activityLabel);
activityLabel.setSize("82px", "36px");
toolboxDragController.makeDraggable(activityLabel);
toolsPanel.add(processLabel);
processLabel.setSize("85px", "36px");
toolboxDragController.makeDraggable(processLabel);
stopDrag.addClickHandler(handler);
toolsPanel.add(stopDrag);
stopDrag.setWidth("114px");
saveButton.addClickHandler(handler);
toolsPanel.add(saveButton);
area.add(canvas, 0, 36);
canvas.setSize("575px", "425px");
Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
//46 is the key code for Delete Button
if(event.getNativeEvent().getKeyCode() == 46 && !selected.isEmpty()) {
for (Iterator<Widget> i = selected.listIterator(); i.hasNext();) {
Widget w = (Widget) i.next();
UIObjectConnector.unwrap(w);
i.remove();
w.removeFromParent();
onCanvas.remove(i);
}
}
}
});
aItems = cu.currentUser.getcActivity();
pItems = cu.currentUser.getcProcess();
}
private class ToolboxDragController extends PickupDragController {
public ToolboxDragController(final DropController dropController, final DragController nodesDragController) {
super(area ,false);
setBehaviorDragProxy(true);
registerDropController(dropController);
addDragHandler(new DragHandlerAdapter(){
public void onPreviewDragEnd(DragEndEvent event) throws VetoDragException {
Widget node = (Widget) event.getSource();
int left = event.getContext().desiredDraggableX;
int top = event.getContext().desiredDraggableY;
AbsolutePanel panel = (AbsolutePanel) dropController.getDropTarget();
createConnector((Label) node, panel, left, top);
throw new VetoDragException();
}
});
}
}
protected UIObjectConnector createConnector(Label proxy, AbsolutePanel panel, int left, int top) {
Widget w;
String str = proxy.getText();
if(str.equals("START") || str.equals("STOP")){
w = new Label(proxy.getText()){
public void onBrowserEvent(Event event) {
if( DOM.eventGetType(event) == 4
&& DOM.eventGetCtrlKey(event)){
select(this);
}
super.onBrowserEvent(event);
}
};
w.getElement().setClassName("dnd-start-stop");
}
else{
w = new ListBox(){
public void onBrowserEvent(Event event) {
if( DOM.eventGetType(event) == 4
&& DOM.eventGetCtrlKey(event)){
select(this);
}
super.onBrowserEvent(event);
}
};
if(str.equals("ACTIVITY")){
getAItems((ListBox)w);
//w.getElement().addClassName("dnd-activity");
}
else if(str.equals("PROCESS")){
getPItems((ListBox)w);
//w.getElement().addClassName("dnd-process");
}
}
onCanvas.add(w);
left -= panel.getAbsoluteLeft();
top -= panel.getAbsoluteTop();
//panel.add(w,10,10);
panel.add(w, left, top);
dragController.makeDraggable(w);
return UIObjectConnector.wrap(w);
}
private void getAItems(ListBox w) {
for(int i=0;i<aItems.length;i++)
w.addItem(aItems[i].getActivityName());
}
private void getPItems(ListBox w) {
/*for(int i=0;i<pItems.length;i++)
w.addItem(pItems[i].getProcessName());*/
w.addItem("Process1");
}
protected void select(Widget w){
if(selected.isEmpty()) {
selected.add(w);
w.getElement().addClassName("color-green");
} else if(selected.contains(w)){
selected.remove(w);
w.getElement().removeClassName("color-green");
} else if(selected.size() == 1) {
Widget w2 = (Widget) selected.get(0);
connect(UIObjectConnector.getWrapper(w2), UIObjectConnector.getWrapper(w));
selected.clear();
}
}
protected void connect(Connector a, Connector b) {
//System.out.println(a.getLeft());
//System.out.println(b.getLeft());
add(new StraightTwoEndedConnection(a,b));
}
private void add(StraightTwoEndedConnection c) {
canvas.add(c);
connections.add(c);
c.update();
}
protected void remove(Connection c) {
connections.remove(c);
}
class MyHandler implements ClickHandler{
#Override
public void onClick(ClickEvent event) {
Button name = (Button) event.getSource();
if(name.equals(stopDrag)){
if(name.getText().equals("Done Dragging")){
for(Iterator<Widget> i = onCanvas.listIterator();i.hasNext();){
Widget w = (Widget) i.next();
dragController.makeNotDraggable(w);
}
name.setText("Continue");
}
else {
for(Iterator<Widget> i = onCanvas.listIterator();i.hasNext();){
Widget w = (Widget) i.next();
dragController.makeDraggable(w);
}
name.setText("Done Dragging");
}
}
else{
}
}
}
}
I know this is quite old, but I was having similar issues with the gwt-connector library.
The connectors will not appear in the correct placement if you are using standards mode. Use quirks mode instead.
Additionally, you need to manually perform a connector.update() while your dnd components are being dragged (in your drag listener) for the connection to move with the endpoint while you are dragging.