📄 managedlist.c
字号:
static const char CVSID[] = "$Id: managedList.c,v 1.12 2003/05/02 19:19:03 edg Exp $";/******************************************************************************** ** managedList.c -- User interface for reorderable list of records ** ** Copyright (C) 1999 Mark Edel ** ** This is free software; you can redistribute it and/or modify it under the ** terms of the GNU General Public License as published by the Free Software ** Foundation; either version 2 of the License, or (at your option) any later ** version. ** ** This software is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ** for more details. ** ** You should have received a copy of the GNU General Public License along with ** software; if not, write to the Free Software Foundation, Inc., 59 Temple ** Place, Suite 330, Boston, MA 02111-1307 USA ** ** Nirvana Text Editor ** November, 1995 ** ** Written by Mark Edel ** ********************************************************************************/#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include "managedList.h"#include "misc.h"#include <stdio.h>#include <string.h>#include <X11/Intrinsic.h>#include <Xm/Form.h>#include <Xm/List.h>#include <Xm/PushB.h>#include <Xm/RowColumn.h>#ifdef HAVE_DEBUG_H#include "../debug.h"#endif/* Common data between the managed list callback functions */typedef struct { Widget listW, deleteBtn, copyBtn, moveUpBtn, moveDownBtn; void *(*getDialogDataCB)(void *, int, int *, void *); void *getDialogDataArg; void (*setDialogDataCB)(void *, void *); void *setDialogDataArg; void *(*copyItemCB)(void *); void (*freeItemCB)(void *); int (*deleteConfirmCB)(int, void *); void *deleteConfirmArg; int maxItems; int *nItems; void **itemList; int lastSelection;} managedListData;static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);static void copyCB(Widget w, XtPointer clientData, XtPointer callData);static void moveUpCB(Widget w, XtPointer clientData, XtPointer callData);static void moveDownCB(Widget w, XtPointer clientData, XtPointer callData);static int incorporateDialogData(managedListData *ml, int listPos, int explicit);static void updateDialogFromList(managedListData *ml, int selection);static void updateListWidgetItem(managedListData *ml, int listPos);static void listSelectionCB(Widget w, XtPointer clientData, XtPointer callData);static int selectedListPosition(managedListData *ml);static void selectItem(Widget listW, int itemIndex, int updateDialog);/*** Create a user interface to help manage a list of arbitrary data records** which users can edit, add, delete, and reorder.**** The caller creates the overall dialog for presenting the data to the user,** but embeds the list and button widgets created here (and list management** code they activate) to handle the organization of the overall list.**** This routine creates a form widget containing the buttons and list widget** with which the user interacts with the list data. ManageListAndButtons** can be used alternatively to take advantage of the management code with a** different arrangement of the widgets (this routine puts buttons in a** column on the left, list on the right) imposed here.**** "args" and "argc" are passed to the form widget creation routine, so that** attachments can be specified for embedding the form in a dialog.**** See ManageListAndButtons for a description of the remaining arguments.*/Widget CreateManagedList(Widget parent, char *name, Arg *args, int argC, void **itemList, int *nItems, int maxItems, int nColumns, void *(*getDialogDataCB)(void *, int, int *, void *), void *getDialogDataArg, void (*setDialogDataCB)(void *, void *), void *setDialogDataArg, void (*freeItemCB)(void *)){ int ac; Arg al[20]; XmString s1; Widget form, rowCol, listW; Widget deleteBtn, copyBtn, moveUpBtn, moveDownBtn; XmString *placeholderTable; char *placeholderStr; form = XmCreateForm(parent, name, args, argC); XtManageChild(form); rowCol = XtVaCreateManagedWidget("mlRowCol", xmRowColumnWidgetClass, form, XmNpacking, XmPACK_COLUMN, XmNleftAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, rowCol, XmNlabelString, s1=XmStringCreateSimple("Delete"), NULL); XmStringFree(s1); copyBtn = XtVaCreateManagedWidget("copy", xmPushButtonWidgetClass, rowCol, XmNlabelString, s1=XmStringCreateSimple("Copy"), NULL); XmStringFree(s1); moveUpBtn = XtVaCreateManagedWidget("moveUp", xmPushButtonWidgetClass, rowCol, XmNlabelString, s1=XmStringCreateSimple("Move ^"), NULL); XmStringFree(s1); moveDownBtn = XtVaCreateManagedWidget("moveDown", xmPushButtonWidgetClass, rowCol, XmNlabelString, s1=XmStringCreateSimple("Move v"), NULL); XmStringFree(s1); /* AFAIK the only way to make a list widget n-columns wide is to make up a fake initial string of that width, and create it with that */ placeholderStr = XtMalloc(nColumns+1); memset(placeholderStr, 'm', nColumns); placeholderStr[nColumns] = '\0'; placeholderTable = StringTable(1, placeholderStr); XtFree(placeholderStr); ac = 0; XtSetArg(al[ac], XmNscrollBarDisplayPolicy, XmAS_NEEDED); ac++; XtSetArg(al[ac], XmNlistSizePolicy, XmCONSTANT); ac++; XtSetArg(al[ac], XmNitems, placeholderTable); ac++; XtSetArg(al[ac], XmNitemCount, 1); ac++; XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++; XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++; XtSetArg(al[ac], XmNleftWidget, rowCol); ac++; XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++; listW = XmCreateScrolledList(form, "list", al, ac); AddMouseWheelSupport(listW); XtManageChild(listW); FreeStringTable(placeholderTable); return ManageListAndButtons(listW, deleteBtn, copyBtn, moveUpBtn, moveDownBtn, itemList, nItems, maxItems, getDialogDataCB, getDialogDataArg, setDialogDataCB, setDialogDataArg, freeItemCB);}/*** Manage a list widget and a set of buttons which represent a list of** records. The caller provides facilities for editing the records** individually, and this code handles the organization of the overall list,** such that the user can modify, add, and delete records, and re-order the** list.**** The format for the list of records managed by this code should be an** array of size "maxItems" of pointers to record structures. The records** themselves can be of any format, but the first field of the structure** must be a pointer to a character string which will be displayed as the** item name in the list. The list "itemList", and the number of items** "nItems" are automatically updated by the list management routines as the** user makes changes.**** The caller must provide routines for transferring data to and from the** dialog fields dedicated to displaying and editing records in the list.** The callback "setDialogDataCB" must take the contents of the item pointer** passed to it, and display the data it contains, erasing any previously** displayed data. The format of the setDialogData callback is:**** void setDialogDataCB(void *item, void *cbArg)**** item: a pointer to the record to be displayed**** cbArg: an arbitrary argument passed on to the callback routine**** The callback "setDialogDataCB" must allocate (with XtMalloc) and return a** new record reflecting the current contents of the dialog fields. It may** do error checking on the data that the user has entered, and can abort** whatever operation triggered the request by setting "abort" to True.** This routine is called in a variety of contexts, such as the user** clicking on a list item, or requesting that a copy be made of the current** list item. To aide in communicating errors to the user, the boolean value** "explicitRequest" distinguishes between the case where the user has** specifically requested that the fields be read, and the case where he** may be surprised that errors are being reported, and require further** explanation. The format of the getDialogData callback is:**** void *getDialogDataCB(void *oldItem, int explicitRequest, int *abort,** void *cbArg)**** oldItem: a pointer to the existing record being modified in the** dialog, or NULL, if the user is modifying the "New" item.**** explicitRequest: True if the user directly asked for the records** to be changed (as with an OK or Apply button). If a less direct** process resulted in the request, the user might need extra** explanation and possibly a chance to proceed using the existing** stored data (to use the data from oldItem, the routine should** make a new copy).**** abort: Can be set to True if the dialog fields contain errors.** Setting abort to True, stops whetever process made the request** for updating the data in the list from the displayed data, and** forces the user to remain focused on the currently displayed** item until he either gives up or gets it right.**** cbArg: arbitrary data, passed on from where the callback was** established in the list creation routines**** The return value should be an allocated**** The callback "freeItemCB" should free the item passed to it:**** void freeItemCB(void *item, void *cbArg)**** item: a pointer to the record to be freed**** The difference between ManageListAndButtons and CreateManagedList, is that** in this routine, the caller creates the list and button widgets and passes** them here so that they be arranged explicitly, rather than relying on the** default style imposed by CreateManagedList. ManageListAndButtons simply** attaches the appropriate callbacks to process mouse and keyboard input from** the widgets.*/Widget ManageListAndButtons(Widget listW, Widget deleteBtn, Widget copyBtn, Widget moveUpBtn, Widget moveDownBtn, void **itemList, int *nItems, int maxItems, void *(*getDialogDataCB)(void *, int, int *, void *), void *getDialogDataArg, void (*setDialogDataCB)(void *, void *), void *setDialogDataArg, void (*freeItemCB)(void *)){ managedListData *ml; /* Create a managedList data structure to hold information about the widgets, callbacks, and current state of the list */ ml = (managedListData *)XtMalloc(sizeof(managedListData)); ml->listW = listW; ml->deleteBtn = deleteBtn; ml->copyBtn = copyBtn; ml->moveUpBtn = moveUpBtn; ml->moveDownBtn = moveDownBtn; ml->getDialogDataCB = NULL; ml->getDialogDataArg = setDialogDataArg; ml->setDialogDataCB = NULL; ml->setDialogDataArg = setDialogDataArg; ml->freeItemCB = freeItemCB; ml->deleteConfirmCB = NULL; ml->deleteConfirmArg = NULL; ml->nItems = nItems; ml->maxItems = maxItems; ml->itemList = itemList; ml->lastSelection = 1; /* Make the managed list data structure accessible from the list widget pointer, and make sure it gets freed when the list is destroyed */ XtVaSetValues(ml->listW, XmNuserData, ml, NULL); XtAddCallback(ml->listW, XmNdestroyCallback, destroyCB, ml); /* Add callbacks for button and list actions */ XtAddCallback(ml->deleteBtn, XmNactivateCallback, deleteCB, ml); XtAddCallback(ml->copyBtn, XmNactivateCallback, copyCB, ml); XtAddCallback(ml->moveUpBtn, XmNactivateCallback, moveUpCB, ml); XtAddCallback(ml->moveDownBtn, XmNactivateCallback, moveDownCB, ml); XtAddCallback(ml->listW, XmNbrowseSelectionCallback, listSelectionCB, ml); /* Initialize the list and buttons (don't set up the callbacks until this is done, so they won't get called on creation) */ updateDialogFromList(ml, -1); ml->getDialogDataCB = getDialogDataCB; ml->setDialogDataCB = setDialogDataCB; return ml->listW;}/*** Update the currently selected list item from the dialog fields, using** the getDialogDataCB callback. "explicitRequest" is a boolean value** passed to on to the getDialogDataCB callback to help set the tone for** how error messages are presented (see ManageListAndButtons for more** information).*/int UpdateManagedList(Widget listW, int explicitRequest){ managedListData *ml; /* Recover the pointer to the managed list structure from the widget's userData pointer */ XtVaGetValues(listW, XmNuserData, &ml, NULL); /* Make the update */ return incorporateDialogData(ml, selectedListPosition(ml), explicitRequest);}/*** Update the displayed list and data to agree with a data list which has** been changed externally (not by the ManagedList list manager).*/void ChangeManagedListData(Widget listW){ managedListData *ml; /* Recover the pointer to the managed list structure from the widget's userData pointer */ XtVaGetValues(listW, XmNuserData, &ml, NULL); updateDialogFromList(ml, -1);}/*** Change the selected item in the managed list given the index into the** list being managed.*/void SelectManagedListItem(Widget listW, int itemIndex){ selectItem(listW, itemIndex, True);}/*** Return the index of the item currently selected in the list*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -