PXDecimalListAttribute converts it to 2 decimals only - acumatica

We want to have a static list for decimal values,
but PXDecimalListAttribute converts it to 2 decimals only while I have defined the DAC field with 4 Decimals.

The PXDecimalListAttribute has fixed formatting to F2 format( 2 decimals) in the FieldSelecting event of the attribute like below:
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
string[] values = Array.ConvertAll<string, string>(this._AllowedValues, (string a) => decimal.Parse(a, NumberStyles.Any, CultureInfo.InvariantCulture).ToString("F2", sender.Graph.Culture));
string[] labels = Array.ConvertAll<string, string>(this._AllowedLabels, (string a) => decimal.Parse(a, NumberStyles.Any, CultureInfo.InvariantCulture).ToString("F2", sender.Graph.Culture));
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, null, null, this._FieldName, null, new int?(-1), null, values, labels, new bool?(this._ExclusiveValues), null, null);
}
You can create your own version of this attribute like below and set it to 4 decimals:
public class PXDecimalListF4Attribute : PXStringListAttribute
{
public PXDecimalListF4Attribute(string[] allowedValues, string[] allowedLabels) : base(allowedValues, allowedLabels)
{
this.IsLocalizable = false;
}
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
string[] values = Array.ConvertAll<string, string>(this._AllowedValues, (string a) => decimal.Parse(a, NumberStyles.Any, CultureInfo.InvariantCulture).ToString("F4", sender.Graph.Culture));
string[] labels = Array.ConvertAll<string, string>(this._AllowedLabels, (string a) => decimal.Parse(a, NumberStyles.Any, CultureInfo.InvariantCulture).ToString("F4", sender.Graph.Culture));
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, null, null, this._FieldName, null, new int?(-1), null, values, labels, new bool?(this._ExclusiveValues), null, null);
}
}
}

Related

RxAndroid onNext being called multiple times

I am calling an api via retrofit with RxAndroid. Here's how the method is defined
#GET("product")
Observable<BaseResponse<List<Product>>> getProducts(#Query("lang") String lang,
#Query("category_id") String category_id,
#Query("start") String start,
#Query("count") String count);
This api returns the list of Product. I wanted to process each Product object inside list to check if that product exists in local db & set the boolean in product object. So I did it like this,
public Observable<List<Product>> getProductList(String catId, int start, int count) {
final List<Product> products = new ArrayList<>();
return RestClient.callApiWrapper(mContext, true, null,
RestClient.get().getProducts("en", catId, "" + start, "" + count))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.flatMapIterable(new Func1<BaseResponse<List<Product>>, Iterable<Product>>() {
#Override
public Iterable<Product> call(BaseResponse<List<Product>> listBaseResponse) {
Log.e("TAG", "flatMapIterable called");
return listBaseResponse.getData();
}
})
.map(new Func1<Product, List<Product>>() {
#Override
public List<Product> call(Product product) {
Log.e("TAG", "map called => " + products.size());
products.add(checkIfProductAddedToCart(product));
return products;
}
});
}
I have subscribed to getProductList where I need the processed list in this way:
mProductListDataModel.getProductList(mCategoryId, mStartOffset, mCount)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Product>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(List<Product> products) {
Log.e("TAG", "onNext => " + products.size());
if(mOnProductListLoaded != null)
mOnProductListLoaded.onProductListLoaded(products);
}
});
Now the problem is, the API actually returns list of 5 products, but onNext is being called 5 times each time with increasing size upto 40 products. Please let me know where I am doing wrong.
I have changed few things for now, which are as below which works for me:
changed getProductList to return Product instead of List<Product>
so it looks like
public Observable<Product> getProductList(String catId, int start, int count) {
//final List<Product> products = new ArrayList<>();
return RestClient.callApiWrapper(mContext, true, null,
RestClient.get().getProducts("en", catId, "" + start, "" + count))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<BaseResponse<List<Product>>, Observable<Product>>() {
#Override
public Observable<Product> call(BaseResponse<List<Product>> listBaseResponse) {
return Observable.from(listBaseResponse.getData());
}
})
.map(new Func1<Product, Product>() {
#Override
public Product call(Product product) {
//Log.e("TAG", "map called => " + products.size());
//products.add(checkIfProductAddedToCart(product));
//return products;
return checkIfProductAddedToCart(product);
}
});
}
and changed following where this observable was subscribed:
final List<Product> products = new ArrayList<>();
mProductListDataModel.getProductList(mCategoryId, mStartOffset, mCount)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Product>() {
#Override
public void onCompleted() {
Log.e("TAG", "onCompleted => " + products.size());
if (mOnProductListLoaded != null)
mOnProductListLoaded.onProductListLoaded(products);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Product product) {
products.add(product);
}
});
However, I am still not sure if this is the right way of doing this. Please let me know if this is not the right way to do so.

JavaFX: Custom traversing with key combinations

I have a table with one editing combobox and three editable text fields,
editable fields create like this:
public class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
#Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Platform.runLater(new Runnable() {
#Override
public void run() {
textField.requestFocus();
textField.selectAll();
}
});
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
} else if (t.getCode() == KeyCode.TAB) {
commitEdit(textField.getText());
TableColumn nextColumn = getNextColumn(!t.isShiftDown());
if (nextColumn != null) {
getTableView().edit(getTableRow().getIndex(), nextColumn);
}
}
}
});
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (!newValue && textField != null) {
commitEdit(textField.getText());
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
/**
*
* #param forward true gets the column to the right, false the column to the left of the current column
* #return
*/
private TableColumn<Person, ?> getNextColumn(boolean forward) {
List<TableColumn<Person, ?>> columns = new ArrayList<>();
for (TableColumn<Person, ?> column : getTableView().getColumns()) {
columns.addAll(getLeaves(column));
}
//There is no other column that supports editing.
if (columns.size() < 2) {
return null;
}
int currentIndex = columns.indexOf(getTableColumn());
int nextIndex = currentIndex;
if (forward) {
nextIndex++;
if (nextIndex > columns.size() - 1) {
nextIndex = 0;
}
} else {
nextIndex--;
if (nextIndex < 0) {
nextIndex = columns.size() - 1;
}
}
return columns.get(nextIndex);
}
private List<TableColumn<Person, ?>> getLeaves(TableColumn<Person, ?> root) {
List<TableColumn<Person, ?>> columns = new ArrayList<>();
if (root.getColumns().isEmpty()) {
//We only want the leaves that are editable.
if (root.isEditable()) {
columns.add(root);
}
return columns;
} else {
for (TableColumn<Person, ?> column : root.getColumns()) {
columns.addAll(getLeaves(column));
}
return columns;
}
}
}
And editable combo column create like this:
public static void createEditingComboColumn(final TableColumn<DUMMY_PurchaseOrderLine, String> Column, final ObservableList<String>comboData, final ObservableList<DUMMY_PurchaseOrderLine> Pdata) {
Column.setCellFactory(new Callback<TableColumn<DUMMY_PurchaseOrderLine,String>,TableCell<DUMMY_PurchaseOrderLine,String>>(){
#Override
public TableCell<DUMMY_PurchaseOrderLine, String> call(TableColumn<DUMMY_PurchaseOrderLine, String> p) {
final TableCell<DUMMY_PurchaseOrderLine, String> cell = new TableCell<DUMMY_PurchaseOrderLine, String>(){
#Override
public void updateItem(String item, boolean empty) {
if(item!=null){
final ComboBox editableComboBox = new ComboBox(comboData);
editableComboBox.setEditable(true);
editableComboBox.setMaxWidth(Double.MAX_VALUE);
Platform.runLater(new Runnable() {
#Override
public void run() {
editableComboBox.requestFocus();
}
});
setGraphic(editableComboBox);
}
}
};
cell.addEventFilter(KeyEvent.KEY_PRESSED,new EventHandler<KeyEvent>(){
#Override
public void handle(KeyEvent t) {
activeRow = cell.getIndex();
if(t.getCode() == KeyCode.TAB||t.getCode() ==KeyCode.RIGHT){
cell.getTableView().edit(cell.getTableRow().getIndex(),cell.getTableView().getColumns().get(1) );
}
}
});
return cell;
}
});
}
Problem: when I press TAB/Right arrow key from any column work properly ,but when I press SHIFT+Tab /left arrow from second column focus goes out. How I focus first column (editing combo) from second column using keyboard?
Thanks....
The condition below in key event handler
if (t.getCode() == KeyCode.TAB)
will handle "TAB" + Any modifier, which means it will handle "Ctrl+TAB", "Alt+TAB", "Shift+Alt+TAB" etc. The same is true for "Right" key. So to handle the "TAB" alone only, the preferred way is to define KeyCodeCombination.
Your posted code is partial, not executable ie. not SSCCE. As I understand your problem lays in key event handling. Because of this I wrote a completely different code but demonstrates the explanation mentioned above. See example, and try to traverse forward with key combination different from "TAB" or "RIGHT". Try with "Ctrl+TAB" or "Alt+RIGHT". It will not work for them, as expected.
public class TraverseDemo extends Application {
#Override
public void start(Stage primaryStage) {
final TextField textField1 = new TextField();
final TextField textField2 = new TextField();
final TextField textField3 = new TextField();
// Diasble all traversals since we will manage them manually, for only textField2.
textField1.setFocusTraversable(false);
textField2.setFocusTraversable(false);
textField3.setFocusTraversable(false);
// Define key combinations for traversals.
final KeyCombination kcTab = KeyCodeCombination.valueOf("TAB");
final KeyCombination kcShiftTab = KeyCodeCombination.valueOf("Shift+TAB");
final KeyCombination kcRight = KeyCodeCombination.valueOf("RIGHT");
final KeyCombination kcLeft = KeyCodeCombination.valueOf("LEFT");
// Default initial focused textfield
requestFocus(textField2);
textField2.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (kcTab.match(t) || kcRight.match(t)) {
System.out.println("traverse forward");
requestFocus(textField3);
} else if (kcShiftTab.match(t) || kcLeft.match(t)) {
System.out.println("traverse backward");
requestFocus(textField1);
}
}
});
StackPane root = new StackPane();
root.getChildren().add(HBoxBuilder.create().spacing(10).children(textField1, textField2, textField3).build());
Scene scene = new Scene(root, 300, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
private void requestFocus(final Node node) {
Platform.runLater(new Runnable() {
#Override
public void run() {
node.requestFocus();
}
});
}
public static void main(String[] args) {
launch(args);
}
}

How to update TableView Row using javaFx

I'm trying to make some downloads and show the progress inside my table:
to do that I'm using the following classes:
public class DownloadDataTable {
private SimpleDoubleProperty progress;
private SimpleStringProperty type;
private SimpleStringProperty status;
public DownloadDataTable(double progress, String type, String status) {
this.progress = new SimpleDoubleProperty(progress);
this.type = new SimpleStringProperty(type);
this.status = new SimpleStringProperty(status);
}
public double getProgress() {
return progress.get();
}
public void setProgress(double progress) {
this.progress.set(progress);
}
public String getType() {
String retorno;
if (type==null){
retorno="";
}else{
retorno=type.get();
}
return retorno;
}
public void setType (String type) {
this.type.set(type);
}
public String getStatus(){
String retorno;
if (status==null){
retorno="";
} else{
retorno=status.get();
}
return retorno;
}
public void setStatus(String status){
this.status.set(status);
}
}
and to create the TitledPane, tableview and column tables I'm doing this:
public void addDownloadToTitledPane(DownloadContent downloadContent) {
MetaDados metaDado = downloadContent.getMetaDado();
String title = metaDado.getName();
if (title.length() > 60) {
title = title.substring(0, 57) + "...";
}
TableView downloadTable = new TableView();
TableColumn<DownloadDataTable, Double> progress = new TableColumn<>("progress");
progress.setCellFactory(new Callback<TableColumn<DownloadDataTable, Double>, TableCell<DownloadDataTable, Double>>() {
#Override
public TableCell<DownloadDataTable, Double> call(TableColumn<DownloadDataTable, Double> p) {
final ProgressBar progressBar = new ProgressBar(-1);
final TableCell cell = new TableCell<DownloadDataTable, Double>() {
#Override
protected void updateItem(Double t, boolean bln) {
super.updateItem(t, bln);
if (bln) {
setText(null);
setGraphic(null);
} else {
progressBar.setProgress(t);
progressBar.prefWidthProperty().bind(this.widthProperty());
setGraphic(progressBar);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
};
cell.setAlignment(Pos.CENTER);
return cell;
}
});
progress.setCellValueFactory(new PropertyValueFactory<DownloadDataTable, Double>("progress"));
progress.setText("Progresso");
TableColumn<DownloadDataTable, String> type = new TableColumn<>("type");
type.setCellFactory(new Callback<TableColumn<DownloadDataTable, String>, TableCell<DownloadDataTable, String>>() {
#Override
public TableCell<DownloadDataTable, String> call(TableColumn<DownloadDataTable, String> p) {
TableCell cell = new TableCell<DownloadDataTable, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
cell.setAlignment(Pos.CENTER);
return cell;
}
});
type.setCellValueFactory(new PropertyValueFactory<DownloadDataTable, String>("type"));
type.setText("Tipo");
TableColumn<DownloadDataTable, String> status = new TableColumn<>("status");
status.setCellFactory(new Callback<TableColumn<DownloadDataTable, String>, TableCell<DownloadDataTable, String>>() {
#Override
public TableCell<DownloadDataTable, String> call(TableColumn<DownloadDataTable, String> p) {
TableCell cell = new TableCell<DownloadDataTable, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : getString());
setGraphic(null);
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
cell.setAlignment(Pos.CENTER);
return cell;
}
});
status.setCellValueFactory(new PropertyValueFactory<DownloadDataTable, String>("status"));
status.setText("Status");
downloadTable.getColumns().addAll(progress, type, status);
List<PendingComponents> pendingComponents = downloadContent.getPendingComponents();
ObservableList<DownloadDataTable> data = FXCollections.observableArrayList();
for (PendingComponents pendingComponent : pendingComponents) {
String typeComponent;
if (pendingComponent.getType().equalsIgnoreCase(Constants.HTML)) {
typeComponent = "Conteúdo Principal";
} else {
typeComponent = "Pacote de Imagens";
}
data.add(new DownloadDataTable(-1, typeComponent, "Preparando download"));
}
downloadTable.setItems(data);
downloadTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TitledPane downloadPane = new TitledPane(title, downloadTable);
downloadPane.setId(metaDado.getOfflineUuid());
vBoxDownload.getChildren().add(downloadPane);
}
Until here everything seems to works fine, but when I try to recover my table and update the data, my table is not updated. I've debbuged and everything seems to work, even the data value is changed, but my table still without update. See my code:
private void publishProgress(final String msg) {
Platform.runLater(new Runnable() {
#Override
public void run() {
TitledPane titledPane = (TitledPane) controller.vBoxDownload.lookup("#"+metaDado.getOfflineUuid());
TableView table = (TableView) titledPane.getContent();
DownloadDataTable data = (DownloadDataTable) table.getItems().get(0);
data.setProgress(100);
data.setStatus(msg);
}
});
}
If I try to remove and add my row it doesn't work, but if I just add another row with the new values, I got a old row with the same value and a new row with new values. I can't figure out what am I doing wrong, someone can help me??
You shouldn't need to add/remove the row to get the table to update when the progress value changes.
The problem is that you're not making the progress property accessible to the TableView. This causes the progress.setCellValueFactory(...) call to wrap your getProgress() value in a new ObservableObjectWrapper. This allows the value to display in the TableView, but it won't notify the table when the value is changed.
Add the following to your DownloadDataTable class, and your table will update when the value changes:
public SimpleDoubleProperty progressProperty() {
return this.progress;
}
public SimpleStringProperty typeProperty() {
return this.type;
}
public SimpleStringProperty statusProperty() {
return this.status;
}

How do insert a record into a from a string using split function in MVC4?

Hi all i have a string like this which i am passing an ajax function to my controller action method
Brand1~1001=>undefined_undefined|
Category1~2001=>1001_Brand1|
Category2~2002=>1001_Brand1|
Product3~3003=>2002_Category2|
Product4~3004=>Product3~3003|
Product5~3005=>2002_Category2|
Product6~3006=>2002_Category2|
and i have an Menus table in db i had added that as an entity model to my project
Menus
[MenuID],[MenuName],[ParentID]
and i have model like this
public class MenuItems
{
public List<MenuItems> GetALL { get; set; }
public int MenuId { get; set; }
public string MenuName { get; set; }
public int parentId { get; set; }
}
now i want to split the string i have and insert into the above table like this
[MenuID],[MenuName],[ParentID]
1001 ,Brand1 ,null
2001 ,category1 ,1001
2002 ,category2 ,1001
3003 ,product3 ,2002
3004 ,product4 ,3003
3005 ,product5 ,2002
3006 ,product6 ,2002
in the above string Brand1~1001=>undefined_undefined| here Brand1~1001 is the parentmenu and 1001 is the id of the menu
Category1~2001=>1001_Brand1| and here Category1~2001 is the sub menu of the 1001_Brand1 i think you all got waht i amtrying to do can any one help me here please
what i amtrying
public ActionResult MenuDrag()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MenuDrag(string menustring)
{
if (!String.IsNullOrEmpty(menustring))
{
string[] menus = menustring.Split('|');
foreach (var m in menus)
{
string[] list = m.Split('>');
//stuck from here confused what to do next and how do i insert the data in my accordingly
}
}
return View();
}
You are almost there just replace your post method with this
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MenuDrag(string menustring)
{
MenuItems items = new MenuItems();
//check the string for empty
if (!String.IsNullOrEmpty(menustring))
{
string[] menus = menustring.Split('|');
foreach (var m in menus)
{
if (m != "")
{
string[] list = m.Split('>');
string[] menu = list[0].Split('~');
string[] parents = list[1].Split('~');
items.MenuItemID = Convert.ToInt16(menu[1]);
items.MenuName = menu[0].ToString();
if (parents[0] == "undefined")
{
items.ParentID = 0;
db.MenuItems.Add(items);
db.SaveChanges();
}
else
{
int parentid=Convert.ToInt16(parents[0]);
var menuid = from me in db.MenusMains where me.MenuItemID == parentid select new { MenuID = me.MenuID };
foreach (var id in menuid)
{
items.ParentID = Convert.ToInt16(id.MenuID);
}
db.MenuItems.Add(items);
db.SaveChanges();
}
}
}
}
return View();
}
}
i had used
if (m != "")
{
}
since u may get an index out of bound exception there since when in your string at this
string[] menus = menustring.Split('|');
u will get an empty ('|') you have to handle this
hope this works

Binding a Table to a Sub Property

There are a couple of answers out there for this already, but I have not been able to find anything conclusive. This is the jist of what I am trying to do:
EquityInstrument
public class EquityInstrument : INotifyPropertyChanged
{
private string _Symbol;
public string Symbol
{
get
{
return _Symbol;
}
set
{
_Symbol = value;
OnPropertyChanged("Symbol");
}
}
public EquityInstrument(string Symbol)
{
this.Symbol = Symbol;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string FieldName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(FieldName);
}
}
}
OptionInstrument
public class OptionInstrument : INotifyPropertyChanged;
{
public readonly EquityInstrument UnderlyingInstrument;
private double _StrikePrice;
public double StrikePrice
{
get
{
return _StrikePrice;
}
set
{
_StrikePrice = value;
OnPropertyChanged("StrikePrice");
}
}
private DateTime _Expiration;
public DateTime Expiration;
{
get
{
return _Expiration;
}
set
{
_Expiration = value;
OnPropertyChanged("Expiration");
}
}
public OptionInstrument(string Symbol, double StrikePrice, DateTime Expiration)
{
this.Symbol = Symbol;
this.StrikePrice = StrikePrice;
this.Expiration = Expiration;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string FieldName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(FieldName);
}
}
}
This code initiates the Option Table...
GridControl OptionGrid = new GridControl();
BindingList<OptionInstrument> BoundList = new BindingList<OptionInstrument>();
public void InitializeDataTable()
{
OptionGrid.DataSource = new BindingSource() { DataSource = BoundList };
BandedGridColumn Column0 = new BandedGridColumn();
Column0.FieldName = "Symbol";
BandedGridColumn Column1 = new BandedGridColumn();
Column1.FieldName = "StrikePrice";
BandedGridColumn Column2 = new BandedGridColumn();
Column2.FieldName = "Expiration";
BandedGridView MainView = (BandedGridView)OptionGrid.MainView;
MainView.Columns.Add(Column0);
MainView.Columns.Add(Column1);
MainView.Columns.Add(Column2);
BoundList.Add(new OptionInstrument("DELL", 12.22, new DateTime(2012, 10, 12));
BoundList.Add(new OptionInstrument("MSFT", 13.23, new DateTime(2012, 09, 16));
BoundList.Add(new OptionInstrument("SPY", 12.23, new DateTime(2012, 07, 18));
}
What do you think? Are there any good design patterns to accomplish this?

Resources