Activation FFNet_Categories_to_Activation (FFNet me, Categories thee) { Activation him = NULL; Categories uniq; long i, nl, cSize = thy size, hasCategories = 1; uniq = Categories_selectUniqueItems (thee, 1); if (uniq == NULL) Melder_error1 (L"There is not enough memory to create a Categories."); if (my outputCategories == NULL) { if (my nUnitsInLayer[my nLayers] == uniq -> size) { my outputCategories = uniq; hasCategories = 0; } else { (void) Melder_error1 (L""); goto end; } } else if (! ( (nl = OrderedOfString_isSubsetOf (uniq, my outputCategories, NULL)) && nl == uniq -> size && my nOutputs >= uniq -> size)) { (void) Melder_error1 (L"The Categories do not match the categories of the FFNet."); goto end; } him = Activation_create (cSize, my nOutputs); if (him == NULL) goto end; for (i=1; i <= cSize; i++) { long pos = OrderedOfString_indexOfItem_c (my outputCategories, OrderedOfString_itemAtIndex_c (thee, i)); if (pos < 1) { (void) Melder_error3 (L"The FFNet doesn't know the category ", OrderedOfString_itemAtIndex_c (thee, i), L" from Categories."); goto end; } his z[i][pos] = 1.0; } end: if (hasCategories) forget (uniq); if (Melder_hasError ()) forget (him); return him; }
static void updateWidgets (CategoriesEditor me) { // all buttons except undo & redo long size = ( (Categories) my data)->size; bool insert = false, insertAtEnd = true, replace = false, remove = false; bool moveUp = false, moveDown = false; long posCount; autoNUMvector<long> posList (GuiList_getSelectedPositions (my list, & posCount), 1); if (posList.peek()) { long firstPos = posList[1], lastPos = posList[posCount]; bool contiguous = ( lastPos - firstPos + 1 == posCount ); moveUp = contiguous && firstPos > 1; moveDown = contiguous && lastPos < size; my position = firstPos; remove = true; replace = true; //insertAtEnd = false; if (posCount == 1) { insert = true; //if (posList[1] == size) insertAtEnd = true; if (size == 1 && ! str32cmp (CategoriesEditor_EMPTYLABEL, OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, 1))) { remove = false; } } } GuiThing_setSensitive (my insert, insert); GuiThing_setSensitive (my insertAtEnd, insertAtEnd); GuiThing_setSensitive (my replace, replace); GuiThing_setSensitive (my remove, remove); GuiThing_setSensitive (my moveUp, moveUp); GuiThing_setSensitive (my moveDown, moveDown); if (my history) { updateUndoAndRedoMenuItems (me); } notifyNumberOfSelected (me); }
autoActivation FFNet_Categories_to_Activation (FFNet me, Categories thee) { try { autoCategories uniq = Categories_selectUniqueItems (thee); if (! my outputCategories) { Melder_throw (U"The FFNet does not have categories."); } long nl = OrderedOfString_isSubsetOf (uniq.get(), my outputCategories.get(), 0); if (nl == 0) { Melder_throw (U"The Categories do not match the categories of the FFNet."); } autoActivation him = Activation_create (thy size, my nOutputs); for (long i = 1; i <= thy size; i ++) { const char32 *citem = OrderedOfString_itemAtIndex_c (thee, i); long pos = OrderedOfString_indexOfItem_c (my outputCategories.get(), citem); if (pos < 1) { Melder_throw (U"The FFNet doesn't know the category ", citem, U"."); } his z [i] [pos] = 1.0; } return him; } catch (MelderError) { Melder_throw (me, U": no Activation created."); } }
static void gui_list_cb_doubleClick (CategoriesEditor me, GuiList_DoubleClickEvent event) { Melder_assert (event -> list == my list); // `my position` should just have been updated by the selectionChanged callback. long posCount; autoNUMvector<long> posList (GuiList_getSelectedPositions (my list, & posCount), 1); if (posCount == 1 // often or even usually true when double-clicking? && posList [1] == my position) // should be true, but we don't crash if it's false { const char32 *catg = OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, my position); if (catg) { // should be non-null, but we don't crash if not GuiText_setString (my text, catg); } } }
autoTableOfReal Matrix_and_Categories_to_TableOfReal (Matrix me, Categories thee) { try { if (thy size != my ny) { Melder_throw (U"Number of rows and number of categories must be equal."); } autoTableOfReal him = TableOfReal_create (my ny, my nx); TableOfReal_setSequentialColumnLabels (him.peek(), 0, 0, nullptr, 1, 1); for (long i = 1; i <= my ny; i ++) { his rowLabels [i] = Melder_dup (OrderedOfString_itemAtIndex_c (thee, i)); } for (long i = 1; i <= my ny; i ++) { for (long j = 1; j <= my nx; j ++) { his data [i] [j] = my z [i] [j]; } } return him; } catch (MelderError) { Melder_throw (U"TableOfReal not created from Matrix & Categories."); } }
TableOfReal Matrix_and_Categories_to_TableOfReal (I, Categories thee) { iam (Matrix); TableOfReal him; long i, j; if (thy size != my ny) return Melder_errorp1 (L"Matrix_and_Categories_to_TableOfReal: " "number of rows and number of categories must be equal."); if (! (him = TableOfReal_create (my ny, my nx)) || ! TableOfReal_setSequentialColumnLabels (him, 0, 0, NULL, 1, 1)) goto end; for (i = 1; i <= my ny; i++) { if (! (his rowLabels[i] = Melder_wcsdup_e (OrderedOfString_itemAtIndex_c (thee, i)))) goto end; } for (i = 1; i <= my ny; i++) { for (j = 1; j <= my nx; j++) his data[i][j] = my z[i][j]; } end: if (Melder_hasError()) forget (him); return him; }
static void update (CategoriesEditor me, long from, long to, const long *select, long nSelect) { long size = ((Categories) my data) -> size; if (size == 0) { autoSimpleString str = SimpleString_create (CategoriesEditor_EMPTYLABEL); Collection_addItem_move ((Categories) my data, str.move()); update (me, 0, 0, nullptr, 0); return; } if (from == 0 && from == to) { from = 1; to = size; } if (from < 1 || from > size) { from = size; } if (to < 1 || to > size) { to = size; } if (from > to) { long ti = from; from = to; to = ti; } // Begin optimization: add the items from a table instead of separately. try { autostring32vector table (from, to); long itemCount = GuiList_getNumberOfItems (my list); for (long i = from; i <= to; i++) { char wcindex[20]; snprintf (wcindex,20, "%5ld ", i); table[i] = Melder_dup_f (Melder_cat (Melder_peek8to32 (wcindex), OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, i))); } if (itemCount > size) { // some items have been removed from Categories? for (long j = itemCount; j > size; j --) { GuiList_deleteItem (my list, j); } itemCount = size; } if (to > itemCount) { for (long j = 1; j <= to - itemCount; j ++) { GuiList_insertItem (my list, table [itemCount + j], 0); } } if (from <= itemCount) { long n = (to < itemCount ? to : itemCount); for (long j = from; j <= n; j++) { GuiList_replaceItem (my list, table[j], j); } } } catch (MelderError) { throw; } // End of optimization // HIGHLIGHT GuiList_deselectAllItems (my list); if (size == 1) { /* the only item is always selected */ const char32 *catg = OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, 1); GuiList_selectItem (my list, 1); updateWidgets (me); // instead of "notify". BUG? GuiText_setString (my text, catg); } else if (nSelect > 0) { // Select but postpone highlighting for (long i = 1; i <= nSelect; i++) { GuiList_selectItem (my list, select[i] > size ? size : select[i]); } } // VIEWPORT { long top = GuiList_getTopPosition (my list), bottom = GuiList_getBottomPosition (my list); long visible = bottom - top + 1; if (nSelect == 0) { top = my position - visible / 2; } else if (select[nSelect] < top) { // selection above visible area top = select[1]; } else if (select[1] > bottom) { // selection below visible area top = select[nSelect] - visible + 1; } else { long deltaTopPos = -1, nUpdate = to - from + 1; if ( (from == select[1] && to == select[nSelect]) || // Replace (nUpdate > 2 && nSelect == 1) /* Inserts */) { deltaTopPos = 0; } else if (nUpdate == nSelect + 1 && select[1] == from + 1) { // down deltaTopPos = 1; } top += deltaTopPos; } if (top + visible > size) { top = size - visible + 1; } if (top < 1) { top = 1; } GuiList_setTopPosition (my list, top); } }