A 2-sash sashform. A 3-level TreeViewer in one and a TableViewer in the other. When it starts no item is selected in the TreeViewer
and the TableViewer shows a list of all the first level objects available. To achieve this, the TreeViewerContainer instantiates the TableViewerContainer and then calls its showFirstLevelItemList( ) method :
public class TableViewerContainer {
private Table table;
private TableViewer tableViewer;
private TableColumnLayout layout;
public TableViewerContainer(SashForm sashForm) {
Composite composite = new Composite(sashForm, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
tableViewer = new TableViewer(composite, SWT.BORDER
| SWT.FULL_SELECTION);
table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
// Add TableColumnLayout
layout = new TableColumnLayout();
composite.setLayout(layout);
}
public void showFirstLevelItemList( FirstLevelItemListContainer obj ) {
// Add the only column
TableViewerColumn tableViewerColumn = new TableViewerColumn(
tableViewer, SWT.NONE);
TableColumn tblclmnFirst = tableViewerColumn.getColumn();
layout.setColumnData(tblclmnFirst, new ColumnWeightData(10,
ColumnWeightData.MINIMUM_WIDTH, false));
tblclmnFirst.setText("Description");
// assign providers and show the table
tableViewer.setLabelProvider(new FirstLevelItemLabelProvider());
tableViewer.setContentProvider(new FirstLevelItemContentProvider());
tableViewer.setInput(obj);
}
This works fine.
Next, selecting an item in the TreeViewer causes the tableViewer to update the data accordingly. To effect this I added a SelectionChangedListener():
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event
.getSelection();
Object obj = selection.getFirstElement();
if (obj instanceof firsLevelDetail ) {
FirstLevelDetail fld = (FirstLevelDetail) obj;
tableViewer.showFirstLevelDetail(fld);
} else if (obj instanceof SecondLevelDetail )
SecondLevelDetail sld = (SecondLevelDetail) obj;
tableViewer.showSecondLevelDetail(sld);
else if (obj instanceof ThirdLevelDetail)
ThirdLevelDetail tld = (ThirdLevelDetail) obj;
tableViewer.showSecondLevelDetail(tld);
}
});`
So that when the user selects a firstLevelItem the TableViewer shows the corresponding data. All the methods called follow the following pattern :
private void showFirstLevelDetail( FirstLevelDetailObj obj ) {
Table tbl = tableViewer.getTable();
tbl.setRedraw(false);
// Dispose former columns
while (tbl.getColumnCount() > 0) {
tbl.getColumns()[0].dispose();
}
// add new columns
TableViewerColumn tableViewerColumn = new TableViewerColumn(
tableViewer, SWT.NONE);
TableColumn tblclmn = tableViewerColumn.getColumn();
layout.setColumnData(tblclmn, new ColumnWeightData(1,
ColumnWeightData.MINIMUM_WIDTH, true));
tblclmn.setText("Code FL Item");
tableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
tblclmn = tableViewerColumn.getColumn();
layout.setColumnData(tblclmn, new ColumnWeightData(1,
ColumnWeightData.MINIMUM_WIDTH, true));
tblclmn.setText("Description FL Item");
tbl.setRedraw(true);
// to avoid an Exception
tableViewer.setInput(null);
// Assign new providers and show the data
tableViewer.setLabelProvider(new FirstLevelDetailLabelProvider());
tableViewer.setContentProvider(new FirstLevelDetailContentProvider());
tableViewer.setInput(obj);
}
The ContentProviders' getElements() methods follow the next patern:
public Object[] getElements(Object inputElement) {
return ((FirstLevelDetail)inputElement).getArrayItems();
}
My problem is after this process the table doesn't show a header or any data until it is resized. Then it works normally until another item is selected, no matter what level the item is.
tableViewer.refresh() does not work.
tableViewer.getTable().redraw() does not work.
All the showXxxxLevelDetail () work properly if they are called in the first place, instead of showFirstLevelItemList() method, provided tableViewer.setInput(null) is commented out.
I'm running Eclipse Indigo, jface 3.8, Windows XP.
I would try to call
composite.layout();
after calling any of those showXXXLevelDetail() methods.
Related
I'm working on a wpf app. visual studio 2022
I have the following code in a file for testing and have set a button click event to run WriteWorkOrderList(). nothing gets passed to it: there are no other methods or anything:
private List<Models.WorkOrder> _workOrderList = new List<Models.WorkOrder>();
public List<Models.WorkOrder> WorkOrderList
{
get
{
return _workOrderList;
}
set
{
if (_workOrderList != value)
{
_workOrderList = value;
NotifyPropertyChanged();
}
}
}
private Models.WorkOrder _currentWorkOrder = new Models.WorkOrder();
public Models.WorkOrder CurrentWorkorder
{
get
{
return _currentWorkOrder;
}
set
{
if (_currentWorkOrder != value)
{
_currentWorkOrder = value;
NotifyPropertyChanged();
}
}
}
public void WriteWorkOrderList()
{
CurrentWorkorder.Customer.Name = "Billy";
WorkOrderList.Add(CurrentWorkorder);
}
I placed a Breakpoint at the beginning of the WriteWorkOrderList()
method
I'll let it continue the first time. and get one record in
WorkOrderList with Customer.Name=Billy.
the second time I click the
button and get to the breakpoint I will change the
CurrentWorkOrder.Customer.Name= "joe".
I'll Step through the code
as soon as the line CurrentWorkorder.Customer.Name = "Billy"; gets processed the record in WorkOrderList updates to the new name
I can't figure out how they are connecting to each other. All I'm trying to do is add a new WorkOrder to the Workorderlist but I haven't Even gotten that far
http://qt-project.org/doc/qt-4.8/qgraphicsscene.html#addItem
said
If the item is already in a different scene, it will first be removed from its old scene, and then added to this scene as a
top-level.
I want to keep the item in old scene.
how can I do this?
myscene1.addItem(item);
myscene2.addItem(item);// I don't want to remove item from myscene1
You can make a copy of the item :
myscene1.addItem(item);
myscene2.addItem(item->clone());
An item cannot occupy two scenes at the same time, in the way that you cannot be in two places at the same time.
The only way to do this is to make a copy of the item and place it in the second scene.
What you could do is to create a new class. e.g.
class Position
{
...
QPoinfF pos;
...
}
Then you can add that class to your item.
class Item : public QGraphicsItem
{
...
public:
void setSharedPos(Position *pos)
{
sharedPosition = pos;
}
//implement the paint(...) function
//its beeing called by the scene
void paint(...)
{
//set the shared position here
setPos(sharedPos);
//paint the item
...
}
protected:
void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
//get the position from the item that could have been moved
//you could also check if the position actually changed
sharedPosition->pos = pos();
}
private
Position *sharedPostion;
...
}
You would no have to create two items and give them both the same pointer to a Position object.
Item *item1 = new Item;
Item *item2 = new Item;
Position *sharedPos = new Position;
item1->setSharedPos(sharedPos);
item2->setSharedPos(sharedPos);
myScene1->addItem(item1);
myScene2->addItem(item2);
They should no at least share their position in the scenes.
If this works then you'll have to change the Position class to fit your needs and it should be working.
I am not quite shure if setting the position in the paint() function works. But thats how I would try to synchronise the items. If it does not work then you'll have to look for another place to update the settings of the items.
Or you could give the items a Pointer to each other and let them change the positions/settings directly.
e.g.
class Item : public QGraphicsItem
{
...
void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
otherItem->setPos(pos());
}
...
void setOtherItem(Item *item)
{
otherItem = item;
}
private:
Item *otherItem;
}
Item *item1 = new Item;
Item *item2 = new Item;
item1->setOtherItem(item2);
item2->setOtherItem(item1);
myScene1->addItem(item1);
myScene2->addItem(item2);
I'm sending a bundle of cards to Glass with the Mirror API (c# library)
I know that you can use the default delete menu item on single cards, but is there a way to provide delete functionality for an entire bundle, ideally the result of one action by the users?
I have successfully used the DELETE action on a menu item with the code below
MenuItem mi = new MenuItem();
mi.Action = "DELETE";
TimelineItem tli = new TimelineItem()
{
Html = itemHtml.ToString(),
Notification = new NotificationConfig() { Level = "DEFAULT" },
MenuItems = new List<MenuItem>() { mi }
};
Is there a way to add this delete menu item to a bundle cover? I know this may be tricky because clicking the bundle cover causes you to navigate into the child cards thus no menu is present like on single cards. I'm looking for something (which I did try but it just ignored the menu item) like this:
MenuItem mi = new MenuItem();
mi.Action = "DELETE";
TimelineItem tli = new TimelineItem()
{
Html = itemHtml.ToString(),
Notification = new NotificationConfig() { Level = "DEFAULT" },
IsBundleCover = true,
BundleId = bundleId,
MenuItems = new List<MenuItem>() { mi }
};
If not possible on a cover card, is there a way to do this for a bundle by adding delete menu items to the child cards?
Any suggestions would be appreciated
You can use customized menu to do this. The code below is using Java but C# should be similar:
Add customized menu item to the card:
List<MenuValue> menuValueList = new ArrayList<MenuValue>();
menuValueList.add(new MenuValue().setIconUrl(iconUrl).setDisplayName("Delete All"));
MenuItem menuItem = new MenuItem();
menuItem.setValues(menuValueList).setId("delete_bundle_A").setAction("CUSTOM");
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(menuItem);
timelineItem.setMenuItems(menuItemList);
Define the controller which handles the callback request of Mirror server notification:
if (notification.getCollection().equals("timeline") && notification.getUserActions().contains(new UserAction().setType("CUSTOM").setPayload("delete_bundle_A"))) {
deleteCards(credential, bundleId);
}
The delete card function:
// if bundleId is null or "", delete all cards
public static void deleteCards(Credential credential, String bundleId) throws IOException {
if (bundleId == null) {
bundleId = "";
}
Mirror.Timeline timelineItems = MirrorClient.getMirror(credential).timeline();
Mirror.Timeline.List list = timelineItems.list();
List<TimelineItem> timelineItemList = null;
do {
TimelineListResponse response = list.execute();
timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
if (bundleId == "" || bundleId.equalsIgnoreCase(item.getBundleId())) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
}
list.setPageToken(response.getNextPageToken());
} else {
break;
}
} while (list.getPageToken() != null && list.getPageToken().length() > 0);
}
Finally, don't forget to subscribe timeline notification when application starts up:
String notifyUrl = "https://mirrornotifications.appspot.com/forward?url=" + "http://yourServer.com/notify";
Subscription subscription = MirrorClient.insertSubscription(credential, notifyUrl, userId, "timeline");
It isn't clear if you're asking how to create the menu items to delete the entire bundle at once, or if you're looking for code to do the actual delete.
Yuan provides some very good answers to both (not least of which because he actually provides code, which I won't), but there are three things you might also want to consider.
1) You can't have a menu on the bundle cover, but if you don't explicitly specify a bundle cover, then the most recent card will be shown as the cover and will also be shown as the first card in the bundle. You'd be able to get to the menu this way. (The default messaging app works this way, for example, but the first card has the same menu as the rest.)
2) You don't need to create a new menu item. You can leverage the DELETE menu item, if you wish. You'll get a delete notification for one of the cards in the bundle and you can then read the bundleId and delete the rest.
3) You don't need to loop through all the cards you've inserted just to find ones that have that bundleId. That is horribly inefficient. I am not fluent in C#, but from reading the documentation at https://developers.google.com/resources/api-libraries/documentation/mirror/v1/csharp/latest/classGoogle_1_1Apis_1_1Mirror_1_1v1_1_1TimelineResource_1_1ListRequest.html, I get the sense that you can create a ListRequest and then set the bundleId before executing the query and get the results.
So I think you can change Yuan's code to something like:
Mirror.Timeline.List list = timelineItems.list();
list.BundleId = bundleId;
List<TimelineItem> timelineItemList = null;
do {
TimelineListResponse response = list.execute();
timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
list.setPageToken(response.getNextPageToken());
} else {
break;
}
} while (list.getPageToken() != null && list.getPageToken().length() > 0);
(this should be treated as pseudo-code, at best)
If you're confident how many items you've put into a bundle, you might also be able to just set list.MaxResults and not have to iterate over the pages of results. So perhaps something more like
Mirror.Timeline.List list = timelineItems.list();
list.BundleId = bundleId;
list.MaxResults = 20; // Set to more than the max number of items in a bundle
TimelineListResponse response = list.execute();
List<TimelineItem> timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
}
There doesn't appear to be a way to delete a bundle in one step but it's still possible...
You can do a GET on /Timeline to get a list of items your app has pushed to the users timeline. Filter that out to find the entries with the bundleId you want to delete. For each of those items, call DELETE /Timeline/{itemid}
I am using Google place API in my application for searching location. When user input text in edit field then the API called and resulted output will shown in a list.
I implemented it successfully but the problem is that each time edit field text changes, the list is not repainting and output is added to the end of the list. I want every time the text changes in the edit text field, the list must remove its previous content that are invalid.
This can be seen in pictures:
For Implementing this, I have written this code:
public final class MyScreen extends MainScreen {
/**
* Creates a new MyScreen object
*/
private Vector _listElements;
ListField list;
JSONObject[] jsonobject;
EditField editfield;
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=";
String[] locationName;
VerticalFieldManager verticalFieldManager = new VerticalFieldManager();
public MyScreen() {
ButtonField search = new ButtonField("Search");
_listElements = new Vector();
list = new ListField();
ListCallback _callback = new ListCallback(this);
// Set the displayed title of the screen
setTitle("Search Edit Field");
editfield = new EditField();
editfield.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
list.invalidate();
createField();
}
});
}
});
list.setCallback(_callback);
add(editfield);
add(new SeparatorField());
verticalFieldManager.add(list);
add(verticalFieldManager);
}
protected void createField() {
ShowList();
reloadList();
}
private void reloadList() {
list.setSize(_listElements.size());
}
class ListCallback implements ListFieldCallback {
MyScreen listDemoScreen;
public ListCallback(MyScreen listDemoScreen) {
this.listDemoScreen = listDemoScreen;
}
public void drawListRow(ListField list, Graphics g, int index, int y,
int w) {
String text = (String) _listElements.elementAt(index);
list.setRowHeight(getFont().getHeight());
g.drawText(text, 0, y, 0, -1);
}
public Object get(ListField list, int index) {
return _listElements.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int string) {
return _listElements.indexOf(prefix, string);
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
}
protected void ShowList() {
HttpConnection httpConn;
InputStream in;
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
String response;
String fieldText = editfield.getText();
connDesc = connFact.getConnection(url + fieldText
+ "%#&sensor=true&key=xxxxxxxxxxxxx"
+ ConnectionType.getConnectionType());
if (connDesc != null) {
httpConn = (HttpConnection) connDesc.getConnection();
try {
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpConnection.HTTP_OK) {
in = httpConn.openInputStream();
StringBuffer buf = new StringBuffer();
int read = -1;
while ((read = in.read()) != -1)
buf.append((char) read);
response = buf.toString();
try {
JSONObject object = new JSONObject(response);
JSONArray ar = object.getJSONArray("predictions");
jsonobject = new JSONObject[ar.length()];
locationName = new String[ar.length()];
list.invalidate();
for (int i = 0; i < ar.length(); i++) {
jsonobject[i] = ar.getJSONObject(i);
_listElements.addElement(jsonobject[i]
.getString("description"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
Dialog.alert("Connection not succeded");
}
}
protected boolean onSavePrompt() {
return true;
}
}
Update and Solution:
only modify this and this rest is working fine. As Peter Suggests, we can also put a Thread.sleep(time); in order to get the UI not blocked:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_listElements.removeAllElements();
createField();
}
});
I think your problem is simply that you do not clear the _listElements Vector when you request more data. So _listElements just gets bigger.
However there is a bigger problem here and that is that your code appears to be running networking operations on the Event Thread. What your should do in your changeListener. is start a Thread that requests the data, then repopulate the ListField when this tread gets data.
As a result of this change, the UI will not be blocked, and the List updates will become asynchronous, so your user could in fact enter another character into the EditField before the first Thread response comes back. To prevent this looking silly, you could delay the Thread processing for a fraction of second to see if another character is entered, and/or you could make sure that the EditField content was still the same as the requested characters before you repopulate it.
I personally prefer this asynchronous approach, but if it bothers you, you could put a 'please wait - loading' type screen to block the user until the response comes back.
Update
Remember that if you start a background Thread, you need to get back onto the Event Thread to do Ui Processing. Typically this is done simply by including your UI code within the run method of a Runnable that is invoked later, for example:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// Ui Code in here
}
});
You should only put Ui Updating code in the runnable. Networking processing, or any other blocking action, should NOT be included.
List does not scroll while adding images in container. I have a list that extends container. I have used two containers for setting image field(left) and text filed(right). while I am adding text filed container list scrolls properly but while adding images in left field it did not scroll please help me . Thank you for your help.
//List declaration
orgNames = new List(tempName);
WidgetRenderer listCheckBoxRenderer = new WidgetRenderer();
orgNames.setListCellRenderer(listCheckBoxRenderer);
orgNames.setFixedSelection(List.FIXED_TRAIL);
organizationDetailsForm.addComponent(orgNames);
OrganizationNameListener orgNameList = new OrganizationNameListener();
orgNames.addActionListener(orgNameList);
//List renderer class
class WidgetRenderer extends Container implements ListCellRenderer {
private Image[] images;
private Button orgImgButton;
private Image orgImg;
private Container contImage, contDet;
private Label orgNameLabel, locationLabel, ratingLabel;
public WidgetRenderer() {
super();
try {
setLayout(new BorderLayout());
contDet = new Container(new BoxLayout(BoxLayout.Y_AXIS));
contImage = new Container();
contDet.setScrollableY(true);
contImage.setScrollable(true);
contDet.setScrollable(true);
contImage.setScrollable(true);
contDet.setSmoothScrolling(true);
contImage.setSmoothScrolling(true);
setScrollable(true);
setScrollableY(true);
orgImgButton = new Button();
orgNameLabel = new Label();
locationLabel = new Label();
Style orgStyle = new Style();
Style locStyle = new Style();
Font font = Font.createSystemFont(Font.FACE_MONOSPACE,
Font.STYLE_BOLD, Font.SIZE_MEDIUM);
orgStyle.setFont(font);
orgNameLabel.setSelectedStyle(orgStyle);
orgNameLabel.setPressedStyle(orgStyle);
orgNameLabel.setUnselectedStyle(orgStyle);
Font font1 = Font.createSystemFont(Font.FACE_MONOSPACE,
Font.STYLE_PLAIN, Font.SIZE_SMALL);
locStyle.setFont(font1);
locationLabel.setSelectedStyle(locStyle);
locationLabel.setPressedStyle(locStyle);
locationLabel.setUnselectedStyle(locStyle);
ratingLabel = new Label();
contImage.addComponent(orgImgButton);
contDet.addComponent(orgNameLabel);
contDet.addComponent(locationLabel);
addComponent(BorderLayout.WEST, contImage);
addComponent(BorderLayout.CENTER, contDet);
} catch (Exception ex) {
System.out.println("ex" + ex.getMessage());
}
}
public Component getListCellRendererComponent(List list, Object value,
int index, boolean isSelected) {
// System.out.println("adding names & loc");
setFocus(isSelected);
for (int i = 0; i < list.size(); i++) {
if (index == i) {
orgNameLabel.setText(tempName[i]);
locationLabel.setText(districtDesc[i] + "," + townDesc[i]);
orgImgButton.setIcon(DefaultLayout.CreateScaledImage(loadImage(thumbnailURL), DefaultLayout.screenWidth()*10/100, DefaultLayout.screenHeight()*9/100));
}
}
if (isSelected) {
getStyle().setBgColor(0x00BFFF);
getStyle().setBgTransparency(100);
} else {
getStyle().setBgTransparency(30);
}
return this;
}
You are invoking scaled() which is a VERY slow and expensive operation within a renderer which must be REALLY fast. Not a good idea. Not sure if that answers your issue but I suggest investigating whether the TRAIL flag is the cause of your issue.