Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

168
LINES

< > BotCompany Repo | #1016978 - DynObjectTable

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (18539L/137K).

abstract sclass DynObjectTable<A> extends DynModule {
  new L<A> data;
  
  transient JTable table;
  transient F1<A, Map> itemToMap;
  transient VF1<A> defaultAction;
  transient bool debug, fieldsInOrder = true, withSearcher;
  transient TableSearcher searcher;
  transient L onListChanged;
  transient Set<S> hideFields;
  transient bool useStruct = false; // possible breaking change for older modules
  
  start {
    itemToMap = func(A a) -> Map {
      if (a instanceof S) ret litorderedmap("" := (S) a);
      Map map = humanizeKeys(fieldsInOrder ? objectToMap_inOrder_withoutFields(a, hideFields) : objectToMap(a));
      if (!useStruct) map = mapValues strOrEmpty(map);
      ret map;
    };
    onChange(r updateTable);
  }
  
  void addCountToName {
    onListChanged = addDyn_sync(onListChanged, r addCountToNameNow);
    addCountToNameNow();
  }
  
  void addCountToNameNow() enter {
    setModuleName(programTitle() + " (" + count() + ")");
  }
  
  visualize {
    L<Map> l = map(itemToMap, data);
    table = dataToTable_uneditable(sexyTable(), l);
    onDoubleClickOrEnter(table, voidfunc(int row) {
      temp enter();
      A a = _get(data, row);
      if (a != null) onDoubleClick(a);
    });
    if (withSearcher)
      ret (searcher = tableWithSearcher2(table)).panel;
    ret table;
  }
  
  void unvisualize() { super.unvisualize(); searcher = null; }
  
  void onDoubleClick(A line) { callF(defaultAction, line); }
  
  void updateTable() enter {
    if (table != null) swing {
      Point scrollPosition = enclosingViewPosition(table);
      if (debug) print("Scroll position: " + scrollPosition);
      dataToTable_uneditable(table, map(itemToMap, data));
      setEnclosingViewPosition(table, scrollPosition);
      if (searcher != null) searcher.rowIndices = null;
      if (debug) print("dataToTable done, alerting " + n2(onListChanged, "listener"));
    }
    pcallFAll(onListChanged);
  }
  
  /*TODO void itemChanged(int row, A entry) {
    if (getRow(row) != entry) {
      fireDataChanged();
      warn("Item index mismatch, recreating table");
    }
    rows.add(dataToTable_makeRow(x, cols));
  }*/
  
  void dontPersist() { _persistenceInfo = mapPlus(_persistenceInfo, data := false); }
  
  void clear() { syncClear(data); fireDataChanged(); }
  void add(A a) { syncAdd(data, a); fireDataChanged(); }
  void add(int idx, A a) { syncAdd(data, idx, a); fireDataChanged(); }
  void addAll(Collection<A> l) { if (empty(l)) ret; syncAddAll(data, l); fireDataChanged(); }
  void addAndScrollDown(A a) { add(a); scrollDown(); }
  void remove(A a) { syncRemove(data, a); fireDataChanged(); }
  void removeAll(L<A> a) { syncRemoveAll(data, a); fireDataChanged(); }
  void setList(Iterable<A> data) { setData(data); }
  void removeSelected() { removeAll(allSelected()); }
  
  // rare legacy binary compatibility workaround
  void setData(Collection<A> data) { setData((Iterable) data); }
  
  void setData(Iterable<A> data) {
    setData(data, false);
  }
  
  void setData(Iterable<A> data, bool force) {
    // ATTN: new logic. test if it works in all cases
    swing {
      //int selection = selectedIndex();
      int[] selection = selectedTableRows_array(table);
      L<A> cloned = cloneList(data);
      if (setField(data := cloned) || force) {
        updateTable();
        dm_vmBus_send listChanged(module(), cloned);
      }
      if (force) change();
      //selectRow(table, selection);
      selectTableRows(table, selection);
    }
  }
  int count() { ret syncL(data); }
  
  void setData_force(Collection<A> data) {
    setData(data, true);
  }
  
  // tries to keep selection
  void fireDataChanged() {
    setData_force(data);
  }
  
  int rowFromSearcher(int i) {
    ret searcher == null || searcher.rowIndices == null ? i : or(get(searcher.rowIndices, i), -1);
  }
  
  A selected() { ret syncGet(data, rowFromSearcher(selectedTableRowInModel(table))); }
  L<A> allSelected() { ret syncListGetMulti(data, selectedIndices()); }
  int selectedIndex() { ret selectedTableRow(table); }
  L<Int> selectedIndices() { ret map(i -> rowFromSearcher(i), selectedTableRowsInModel(table)); }
  bool selectItem(A a) { int i = indexOf(data, a); selectRow(table, i); ret i >= 0; } // true if item exists
  void doubleClickItem(A a) { if (selectItem(a)) onDoubleClick(a); }
  
  // r : Runnable or VF1<A>
  // run only in visualize()!
  void popupMenuItem(S text, O r) {
    tablePopupMenuItemsThreaded(table, text, _convertRunnable(r));
  }
  
  void popupMenuItem_top(S text, O r) {
    tablePopupMenuItemsThreaded_top(table, text, _convertRunnable(r));
  }
  
  // row index => element
  O _convertRunnable(fO r) {
    if (r == null || r instanceof Runnable) ret r;
    ret voidfunc(int idx) { callF(r, syncGet(data, idx)) };
  }
  
  JTable table() { ret table; }
  
  void hideFields(S... fields) {
    if (hideFields == null) hideFields = new Set;
    _addAll(hideFields, fields);
  }
  
  A getRow(int row) { ret get(data, row); }
  
  void scrollDown { scrollTableDownNow(table); }
  
  // API
  
  L<A> getData() { ret data; } // data is usually immutable
  L<A> data() { ret getData(); }
  L<A> list() { ret getData(); }
  L<A> getList() { ret getData(); }
  
  L<A> clonedList() { ret cloneList(data); }
  
  // log list (and whole module) contents somewhere
  File quickBackup() {
    File f = programFile("backup-" + ymd_minus_hms_minus_millis() + ".gz");
    saveGZStructToFile(f, module());
    printFileInfo(f);
    ret f;
  }
}

Author comment

Began life as a copy of #1016065

download  show line numbers  debug dex   

Travelled to 11 computer(s): aoiabmzegqzx, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, tslmcundralx, tvejysmllsmz

No comments. add comment

Snippet ID: #1016978
Snippet name: DynObjectTable
Eternal ID of this version: #1016978/101
Text MD5: 29b299ef70ca837e7e7578d267a467c3
Transpilation MD5: 5dcfffd5d2b1e7a52ea7a37ee09a9c2d
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-02-18 20:01:55
Source code size: 5650 bytes / 168 lines
Pitched / IR pitched: No / No
Views / Downloads: 491 / 1632
Version history: 100 change(s)
Referenced in: #1003674 #1019849

Formerly at http://tinybrain.de/1016978 & http://1016978.tinybrain.de