X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/WINGs/wfontpanel.c diff --git a/WINGs/wfontpanel.c b/WINGs/wfontpanel.c dissimilarity index 92% index c03a7792..523f85ce 100644 --- a/WINGs/wfontpanel.c +++ b/WINGs/wfontpanel.c @@ -1,900 +1,805 @@ - - - - -#include "WINGsP.h" -#include "WUtil.h" -#include "wconfig.h" - -#include -#include -#include - -#include -#include - - -/* XXX TODO */ -char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification"; - - - - -typedef struct W_FontPanel { - WMWindow *win; - - WMFrame *upperF; - WMTextField *sampleT; - - WMSplitView *split; - - WMFrame *lowerF; - WMLabel *famL; - WMList *famLs; - WMLabel *typL; - WMList *typLs; - WMLabel *sizL; - WMTextField *sizT; - WMList *sizLs; - - WMAction2 *action; - void *data; - - WMButton *revertB; - WMButton *setB; - - WMPropList *fdb; -} FontPanel; - - -#define MIN_UPPER_HEIGHT 20 -#define MIN_LOWER_HEIGHT 140 - - -#define MAX_FONTS_TO_RETRIEVE 2000 - -#define BUTTON_SPACE_HEIGHT 40 - -#define MIN_WIDTH 250 -#define MIN_HEIGHT (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT) - -#define DEF_UPPER_HEIGHT 60 -#define DEF_LOWER_HEIGHT 310 - -#define DEF_WIDTH 320 -#define DEF_HEIGHT (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT) - - - - -static int scalableFontSizes[] = { - 8, - 10, - 11, - 12, - 14, - 16, - 18, - 20, - 24, - 36, - 48, - 64 -}; - - - -static void setFontPanelFontName(FontPanel *panel, char *family, char *style, double size); - -static int isXLFD(char *font, int *length_ret); - -static void arrangeLowerFrame(FontPanel *panel); - -static void familyClick(WMWidget *, void *); -static void typefaceClick(WMWidget *, void *); -static void sizeClick(WMWidget *, void *); - - -static void listFamilies(WMScreen *scr, WMFontPanel *panel); - - -static void -splitViewConstrainCallback(WMSplitView *sPtr, int indView, int *min, int *max) -{ - if (indView == 0) - *min = MIN_UPPER_HEIGHT; - else - *min = MIN_LOWER_HEIGHT; -} - -static void -notificationObserver(void *self, WMNotification *notif) -{ - WMFontPanel *panel = (WMFontPanel*)self; - void *object = WMGetNotificationObject(notif); - - if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) { - if (object == WMWidgetView(panel->win)) { - int h = WMWidgetHeight(panel->win); - int w = WMWidgetWidth(panel->win); - - WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT); - - WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5)); - - WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5)); - - } else if (object == WMWidgetView(panel->upperF)) { - - if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) { - WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), - MIN_UPPER_HEIGHT); - } else { - WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20, - WMWidgetHeight(panel->upperF)-10); - } - - } else if (object == WMWidgetView(panel->lowerF)) { - - if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) { - WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), - MIN_UPPER_HEIGHT); - - WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF) - + WMGetSplitViewDividerThickness(panel->split)); - - WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF), - WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT - - WMGetSplitViewDividerThickness(panel->split)); - } else { - arrangeLowerFrame(panel); - } - } - } -} - - -static void -closeWindow(WMWidget *w, void *data) -{ - FontPanel *panel = (FontPanel*)data; - - WMHideFontPanel(panel); -} - - - - -static void -setClickedAction(WMWidget *w, void *data) -{ - FontPanel *panel = (FontPanel*)data; - - if (panel->action) - (*panel->action)(panel, panel->data); -} - - -static void -revertClickedAction(WMWidget *w, void *data) -{ - /*FontPanel *panel = (FontPanel*)data;*/ - /* XXX TODO */ -} - - - -WMFontPanel* -WMGetFontPanel(WMScreen *scr) -{ - FontPanel *panel; - WMColor *dark, *white; - WMFont *font; - int divThickness; - - if (scr->sharedFontPanel) - return scr->sharedFontPanel; - - - panel = wmalloc(sizeof(FontPanel)); - memset(panel, 0, sizeof(FontPanel)); - - panel->win = WMCreateWindow(scr, "fontPanel"); - /* WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/ - WMSetWindowTitle(panel->win, _("Font Panel")); - WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT); - WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT); - WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True); - - WMSetWindowCloseAction(panel->win, closeWindow, panel); - - panel->split = WMCreateSplitView(panel->win); - WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT); - WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback); - - divThickness = WMGetSplitViewDividerThickness(panel->split); - - panel->upperF = WMCreateFrame(panel->win); - WMSetFrameRelief(panel->upperF, WRFlat); - WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True); - panel->lowerF = WMCreateFrame(panel->win); - /* WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/ - WMSetFrameRelief(panel->lowerF, WRFlat); - WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True); - - WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF)); - WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF)); - - WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT); - - WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT); - - WMMoveWidget(panel->lowerF, 0, 60+divThickness); - - white = WMWhiteColor(scr); - dark = WMDarkGrayColor(scr); - - panel->sampleT = WMCreateTextField(panel->upperF); - WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50); - WMMoveWidget(panel->sampleT, 10, 10); - WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog")); - - font = WMBoldSystemFontOfSize(scr, 12); - - panel->famL = WMCreateLabel(panel->lowerF); - WMSetWidgetBackgroundColor(panel->famL, dark); - WMSetLabelText(panel->famL, _("Family")); - WMSetLabelFont(panel->famL, font); - WMSetLabelTextColor(panel->famL, white); - WMSetLabelRelief(panel->famL, WRSunken); - WMSetLabelTextAlignment(panel->famL, WACenter); - - panel->famLs = WMCreateList(panel->lowerF); - WMSetListAction(panel->famLs, familyClick, panel); - - panel->typL = WMCreateLabel(panel->lowerF); - WMSetWidgetBackgroundColor(panel->typL, dark); - WMSetLabelText(panel->typL, _("Typeface")); - WMSetLabelFont(panel->typL, font); - WMSetLabelTextColor(panel->typL, white); - WMSetLabelRelief(panel->typL, WRSunken); - WMSetLabelTextAlignment(panel->typL, WACenter); - - panel->typLs = WMCreateList(panel->lowerF); - WMSetListAction(panel->typLs, typefaceClick, panel); - - panel->sizL = WMCreateLabel(panel->lowerF); - WMSetWidgetBackgroundColor(panel->sizL, dark); - WMSetLabelText(panel->sizL, _("Size")); - WMSetLabelFont(panel->sizL, font); - WMSetLabelTextColor(panel->sizL, white); - WMSetLabelRelief(panel->sizL, WRSunken); - WMSetLabelTextAlignment(panel->sizL, WACenter); - - panel->sizT = WMCreateTextField(panel->lowerF); - /* WMSetTextFieldAlignment(panel->sizT, WARight);*/ - - panel->sizLs = WMCreateList(panel->lowerF); - WMSetListAction(panel->sizLs, sizeClick, panel); - - WMReleaseFont(font); - WMReleaseColor(white); - WMReleaseColor(dark); - - panel->setB = WMCreateCommandButton(panel->win); - WMResizeWidget(panel->setB, 70, 24); - WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5)); - WMSetButtonText(panel->setB, _("Set")); - WMSetButtonAction(panel->setB, setClickedAction, panel); - - panel->revertB = WMCreateCommandButton(panel->win); - WMResizeWidget(panel->revertB, 70, 24); - WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5)); - WMSetButtonText(panel->revertB, _("Revert")); - WMSetButtonAction(panel->revertB, revertClickedAction, panel); - - - WMRealizeWidget(panel->win); - - WMMapSubwidgets(panel->upperF); - WMMapSubwidgets(panel->lowerF); - WMMapSubwidgets(panel->split); - WMMapSubwidgets(panel->win); - - WMUnmapWidget(panel->revertB); - - arrangeLowerFrame(panel); - - scr->sharedFontPanel = panel; - - - /* register notification observers */ - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->win)); - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->upperF)); - WMAddNotificationObserver(notificationObserver, panel, - WMViewSizeDidChangeNotification, - WMWidgetView(panel->lowerF)); - - - listFamilies(scr, panel); - - - return panel; -} - - -void -WMFreeFontPanel(WMFontPanel *panel) -{ - if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) { - WMWidgetScreen(panel->win)->sharedFontPanel = NULL; - } - WMRemoveNotificationObserver(panel); - WMUnmapWidget(panel->win); - WMDestroyWidget(panel->win); - wfree(panel); -} - - -void -WMShowFontPanel(WMFontPanel *panel) -{ - WMMapWidget(panel->win); -} - - -void -WMHideFontPanel(WMFontPanel *panel) -{ - WMUnmapWidget(panel->win); -} - - -WMFont* -WMGetFontPanelFont(WMFontPanel *panel) -{ - return WMGetTextFieldFont(panel->sampleT); -} - - -void -WMSetFontPanelFont(WMFontPanel *panel, char *fontName) -{ - int fname_len; - FcPattern *pattern; - FcChar8 *family, *style; - double size; - - if (!isXLFD(fontName, &fname_len)) { - /* maybe its proper fontconfig and we can parse it */ - pattern = FcNameParse((FcChar8*)fontName); - } else { - /* maybe its proper xlfd and we can convert it to an FcPattern */ - pattern = XftXlfdParse(fontName, False, False); - /*//FcPatternPrint(pattern);*/ - } - - if (!pattern) - return; - - if (FcPatternGetString(pattern, FC_FAMILY, 0, &family)==FcResultMatch) - if (FcPatternGetString(pattern, FC_STYLE, 0, &style)==FcResultMatch) - if (FcPatternGetDouble(pattern, "pixelsize", 0, &size)==FcResultMatch) - setFontPanelFontName(panel, (char*)family, (char*)style, size); - - FcPatternDestroy(pattern); -} - - -void -WMSetFontPanelAction(WMFontPanel *panel, WMAction2 *action, void *data) -{ - panel->action = action; - panel->data = data; -} - - - - - -static void -arrangeLowerFrame(FontPanel *panel) -{ - int width = WMWidgetWidth(panel->lowerF) - 55 - 30; - int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF); - int fw, tw, sw; - -#define LABEL_HEIGHT 20 - - height -= WMGetSplitViewDividerThickness(panel->split); - - - height -= LABEL_HEIGHT + 8; - - fw = (125*width) / 235; - tw = (110*width) / 235; - sw = 55; - - WMMoveWidget(panel->famL, 10, 0); - WMResizeWidget(panel->famL, fw, LABEL_HEIGHT); - - WMMoveWidget(panel->famLs, 10, 23); - WMResizeWidget(panel->famLs, fw, height); - - WMMoveWidget(panel->typL, 10+fw+3, 0); - WMResizeWidget(panel->typL, tw, LABEL_HEIGHT); - - WMMoveWidget(panel->typLs, 10+fw+3, 23); - WMResizeWidget(panel->typLs, tw, height); - - WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0); - WMResizeWidget(panel->sizL, sw+4, LABEL_HEIGHT); - - WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23); - WMResizeWidget(panel->sizT, sw+4, 20); - - WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46); - WMResizeWidget(panel->sizLs, sw+4, height-23); -} - - - -#define NUM_FIELDS 14 - - -static int -isXLFD(char *font, int *length_ret) -{ - int c = 0; - - *length_ret = 0; - while (*font) { - (*length_ret)++; - if (*font++ == '-') - c++; - } - - return c==NUM_FIELDS; -} - - -typedef struct { - char *typeface; - WMArray *sizes; -} Typeface; - -typedef struct { - char *name; /* gotta love simplicity */ - WMArray *typefaces; -} Family; - - -static int -compare_int(const void *a, const void *b) -{ - int i1 = *(int*)a; - int i2 = *(int*)b; - - if (i1 < i2) - return -1; - else if (i1 > i2) - return 1; - else - return 0; -} - - -static void -addSizeToTypeface(Typeface *face, int size) -{ - if (size == 0) { - int j; - - for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) { - size = scalableFontSizes[j]; - - if (!WMCountInArray(face->sizes, (void*)(uintptr_t)size)) { - WMAddToArray(face->sizes, (void*)(uintptr_t)size); - } - } - WMSortArray(face->sizes, compare_int); - } else { - if (!WMCountInArray(face->sizes, (void*)(uintptr_t)size)) { - WMAddToArray(face->sizes, (void*)(uintptr_t)size); - WMSortArray(face->sizes, compare_int); - } - } -} - -static void -addTypefaceToXftFamily(Family *fam, char *style) -{ - Typeface *face; - WMArrayIterator i; - - if(fam->typefaces) { - WM_ITERATE_ARRAY(fam->typefaces, face, i) { - if(strcmp(face->typeface, style) != 0) - continue; /* go to next interation */ - addSizeToTypeface(face, 0); - return; - } - } else { - fam->typefaces = WMCreateArray(4); - } - - face = wmalloc(sizeof(Typeface)); - memset(face, 0 , sizeof(Typeface)); - - face->typeface = wstrdup(style); - face->sizes = WMCreateArray(4); - addSizeToTypeface(face, 0); - - WMAddToArray(fam->typefaces, face); -} - -/* - * families (same family name) (Hashtable of family -> array) - * registries (same family but different registries) - * - */ -static void -addFontToXftFamily(WMHashTable *families, char *name, char *style) -{ - WMArrayIterator i; - WMArray *array; - Family *fam; - - array = WMHashGet(families, name); - if(array) { - WM_ITERATE_ARRAY(array, fam, i) { - if(strcmp(fam->name, name) == 0 ) - addTypefaceToXftFamily(fam, style); - return; - } - } - - array = WMCreateArray(8); - - fam = wmalloc(sizeof(Family)); - memset(fam, 0, sizeof(Family)); - - fam->name = wstrdup(name); - - addTypefaceToXftFamily(fam, style); - - WMAddToArray(array, fam); - - WMHashInsert(families, fam->name, array); -} - - -static void -listFamilies(WMScreen *scr, WMFontPanel *panel) -{ - FcObjectSet *os = 0; - FcFontSet *fs; - FcPattern *pat; - WMHashTable *families; - WMHashEnumerator enumer; - WMArray *array; - int i; - - pat = FcPatternCreate(); - os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL); - fs = FcFontList(0, pat, os); - if (!fs) { - WMRunAlertPanel(scr, panel->win, _("Error"), - _("Could not init font config library\n"), _("OK"), NULL, NULL); - return; - } - if (pat) - FcPatternDestroy (pat); - - families = WMCreateHashTable(WMStringPointerHashCallbacks); - - if(fs) { - for (i = 0; i < fs->nfont; i++) { - FcChar8 *family; - FcChar8 *style; - - if (FcPatternGetString(fs->fonts[i],FC_FAMILY,0,&family)==FcResultMatch) - if (FcPatternGetString(fs->fonts[i],FC_STYLE,0,&style)==FcResultMatch) - addFontToXftFamily(families, (char*)family, (char*)style); - } - FcFontSetDestroy(fs); - } - - enumer = WMEnumerateHashTable(families); - - while ((array = WMNextHashEnumeratorItem(&enumer))) { - WMArrayIterator i; - Family *fam; - char buffer[256]; - WMListItem *item; - - WM_ITERATE_ARRAY(array, fam, i) { - strcpy(buffer, fam->name); - item = WMAddListItem(panel->famLs, buffer); - - item->clientData = fam; - } - - WMFreeArray(array); - } - - WMSortListItems(panel->famLs); - - WMFreeHashTable(families); -} - - -static void -getSelectedFont(FontPanel *panel, char buffer[], int bufsize) -{ - WMListItem *item; - Family *family; - Typeface *face; - char *size; - - - item = WMGetListSelectedItem(panel->famLs); - if (!item) - return; - family = (Family*)item->clientData; - - item = WMGetListSelectedItem(panel->typLs); - if (!item) - return; - face = (Typeface*)item->clientData; - - size = WMGetTextFieldText(panel->sizT); - - snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s", - family->name, - face->typeface, - size); - - wfree(size); -} - - - -static void -preview(FontPanel *panel) -{ - char buffer[512]; - WMFont *font; - - getSelectedFont(panel, buffer, sizeof(buffer)); - font = WMCreateFont(WMWidgetScreen(panel->win), buffer); - if (font) { - WMSetTextFieldFont(panel->sampleT, font); - WMReleaseFont(font); - } -} - - - -static void -familyClick(WMWidget *w, void *data) -{ - WMList *lPtr = (WMList*)w; - WMListItem *item; - Family *family; - Typeface *face; - FontPanel *panel = (FontPanel*)data; - WMArrayIterator i; - /* current typeface and size */ - char *oface = NULL; - char *osize = NULL; - int facei = -1; - int sizei = -1; - - /* must try to keep the same typeface and size for the new family */ - item = WMGetListSelectedItem(panel->typLs); - if (item) - oface = wstrdup(item->text); - - osize = WMGetTextFieldText(panel->sizT); - - - item = WMGetListSelectedItem(lPtr); - family = (Family*)item->clientData; - - WMClearList(panel->typLs); - - - WM_ITERATE_ARRAY(family->typefaces, face, i) { - char buffer[256]; - int top=0; - WMListItem *fitem; - - strcpy(buffer, face->typeface); - if(strcasecmp(face->typeface, "Roman") == 0) - top = 1; - if(strcasecmp(face->typeface, "Regular") == 0) - top = 1; - if (top) - fitem = WMInsertListItem(panel->typLs, 0, buffer); - else - fitem = WMAddListItem(panel->typLs, buffer); - fitem->clientData = face; - } - - if (oface) { - facei = WMFindRowOfListItemWithTitle(panel->typLs, oface); - wfree(oface); - } - if (facei < 0) { - facei = 0; - } - WMSelectListItem(panel->typLs, facei); - typefaceClick(panel->typLs, panel); - - if (osize) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); - } - if (sizei >= 0) { - WMSelectListItem(panel->sizLs, sizei); - sizeClick(panel->sizLs, panel); - } - - if (osize) - wfree(osize); - - - preview(panel); -} - - -static void -typefaceClick(WMWidget *w, void *data) -{ - FontPanel *panel = (FontPanel*)data; - WMListItem *item; - Typeface *face; - WMArrayIterator i; - char buffer[32]; - - char *osize = NULL; - int sizei = -1; - void *size; - - osize = WMGetTextFieldText(panel->sizT); - - - item = WMGetListSelectedItem(panel->typLs); - face = (Typeface*)item->clientData; - - WMClearList(panel->sizLs); - - WM_ITERATE_ARRAY(face->sizes, size, i) { - if ((int)(uintptr_t)size != 0) { - sprintf(buffer, "%i", (int)(uintptr_t)size); - - WMAddListItem(panel->sizLs, buffer); - } - } - - if (osize) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); - } - if (sizei < 0) { - sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12"); - } - if (sizei < 0) { - sizei = 0; - } - WMSelectListItem(panel->sizLs, sizei); - WMSetListPosition(panel->sizLs, sizei); - sizeClick(panel->sizLs, panel); - - if (osize) - wfree(osize); - - preview(panel); -} - -static void -sizeClick(WMWidget *w, void *data) -{ - FontPanel *panel = (FontPanel*)data; - WMListItem *item; - - item = WMGetListSelectedItem(panel->sizLs); - WMSetTextFieldText(panel->sizT, item->text); - - WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text))); - - preview(panel); -} - - -static void -setFontPanelFontName(FontPanel *panel, char *family, char *style, double size) -{ - int famrow; - int stlrow; - int sz; - char asize[64]; - void *vsize; - WMListItem *item; - Family *fam; - Typeface *face; - WMArrayIterator i; - - famrow = WMFindRowOfListItemWithTitle(panel->famLs, family); - if (famrow < 0 ){ - famrow = 0; - return; - } - WMSelectListItem(panel->famLs, famrow); - WMSetListPosition(panel->famLs, famrow); - - WMClearList(panel->typLs); - - item = WMGetListSelectedItem(panel->famLs); - - fam = (Family*)item->clientData; - WM_ITERATE_ARRAY(fam->typefaces, face, i) { - char buffer[256]; - int top=0; - WMListItem *fitem; - - strcpy(buffer, face->typeface); - if(strcasecmp(face->typeface, "Roman") == 0) - top = 1; - if (top) - fitem = WMInsertListItem(panel->typLs, 0, buffer); - else - fitem = WMAddListItem(panel->typLs, buffer); - fitem->clientData = face; - } - - - stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style); - - if (stlrow < 0) { - stlrow = 0; - return; - } - - WMSelectListItem(panel->typLs, stlrow); - - item = WMGetListSelectedItem(panel->typLs); - - face = (Typeface*)item->clientData; - - WMClearList(panel->sizLs); - - - WM_ITERATE_ARRAY(face->sizes, vsize, i) { - char buffer[32]; - if ((int)(uintptr_t)vsize != 0) { - sprintf(buffer, "%i", (int)(uintptr_t)vsize); - - WMAddListItem(panel->sizLs, buffer); - } - } - - snprintf(asize, sizeof(asize)-1, "%d",(int)(size+0.5)); - - sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize); - - if (sz < 0) { - sz = 4; - return; - } - - WMSelectListItem(panel->sizLs, sz); - sizeClick(panel->sizLs, panel); - - return; -} - - + +#include "WINGsP.h" +#include "WUtil.h" +#include "wconfig.h" + +#include +#include +#include + +#include +#include + +/* XXX TODO */ +char *WMFontPanelFontChangedNotification = "WMFontPanelFontChangedNotification"; + +typedef struct W_FontPanel { + WMWindow *win; + + WMFrame *upperF; + WMTextField *sampleT; + + WMSplitView *split; + + WMFrame *lowerF; + WMLabel *famL; + WMList *famLs; + WMLabel *typL; + WMList *typLs; + WMLabel *sizL; + WMTextField *sizT; + WMList *sizLs; + + WMAction2 *action; + void *data; + + WMButton *revertB; + WMButton *setB; + + WMPropList *fdb; +} FontPanel; + +#define MIN_UPPER_HEIGHT 20 +#define MIN_LOWER_HEIGHT 140 + +#define MAX_FONTS_TO_RETRIEVE 2000 + +#define BUTTON_SPACE_HEIGHT 40 + +#define MIN_WIDTH 250 +#define MIN_HEIGHT (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT) + +#define DEF_UPPER_HEIGHT 60 +#define DEF_LOWER_HEIGHT 310 + +#define DEF_WIDTH 320 +#define DEF_HEIGHT (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT) + +static int scalableFontSizes[] = { + 8, + 10, + 11, + 12, + 14, + 16, + 18, + 20, + 24, + 36, + 48, + 64 +}; + +static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size); + +static int isXLFD(char *font, int *length_ret); + +static void arrangeLowerFrame(FontPanel * panel); + +static void familyClick(WMWidget *, void *); +static void typefaceClick(WMWidget *, void *); +static void sizeClick(WMWidget *, void *); + +static void listFamilies(WMScreen * scr, WMFontPanel * panel); + +static void splitViewConstrainCallback(WMSplitView * sPtr, int indView, int *min, int *max) +{ + if (indView == 0) + *min = MIN_UPPER_HEIGHT; + else + *min = MIN_LOWER_HEIGHT; +} + +static void notificationObserver(void *self, WMNotification * notif) +{ + WMFontPanel *panel = (WMFontPanel *) self; + void *object = WMGetNotificationObject(notif); + + if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) { + if (object == WMWidgetView(panel->win)) { + int h = WMWidgetHeight(panel->win); + int w = WMWidgetWidth(panel->win); + + WMResizeWidget(panel->split, w, h - BUTTON_SPACE_HEIGHT); + + WMMoveWidget(panel->setB, w - 80, h - (BUTTON_SPACE_HEIGHT - 5)); + + WMMoveWidget(panel->revertB, w - 240, h - (BUTTON_SPACE_HEIGHT - 5)); + + } else if (object == WMWidgetView(panel->upperF)) { + + if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) { + WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT); + } else { + WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF) - 20, + WMWidgetHeight(panel->upperF) - 10); + } + + } else if (object == WMWidgetView(panel->lowerF)) { + + if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) { + WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), MIN_UPPER_HEIGHT); + + WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF) + + WMGetSplitViewDividerThickness(panel->split)); + + WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF), + WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT + - WMGetSplitViewDividerThickness(panel->split)); + } else { + arrangeLowerFrame(panel); + } + } + } +} + +static void closeWindow(WMWidget * w, void *data) +{ + FontPanel *panel = (FontPanel *) data; + + WMHideFontPanel(panel); +} + +static void setClickedAction(WMWidget * w, void *data) +{ + FontPanel *panel = (FontPanel *) data; + + if (panel->action) + (*panel->action) (panel, panel->data); +} + +static void revertClickedAction(WMWidget * w, void *data) +{ + /*FontPanel *panel = (FontPanel*)data; */ + /* XXX TODO */ +} + +WMFontPanel *WMGetFontPanel(WMScreen * scr) +{ + FontPanel *panel; + WMColor *dark, *white; + WMFont *font; + int divThickness; + + if (scr->sharedFontPanel) + return scr->sharedFontPanel; + + panel = wmalloc(sizeof(FontPanel)); + memset(panel, 0, sizeof(FontPanel)); + + panel->win = WMCreateWindow(scr, "fontPanel"); + /* WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr)); */ + WMSetWindowTitle(panel->win, _("Font Panel")); + WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT); + WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT); + WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True); + + WMSetWindowCloseAction(panel->win, closeWindow, panel); + + panel->split = WMCreateSplitView(panel->win); + WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT); + WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback); + + divThickness = WMGetSplitViewDividerThickness(panel->split); + + panel->upperF = WMCreateFrame(panel->win); + WMSetFrameRelief(panel->upperF, WRFlat); + WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True); + panel->lowerF = WMCreateFrame(panel->win); + /* WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr)); */ + WMSetFrameRelief(panel->lowerF, WRFlat); + WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True); + + WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF)); + WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF)); + + WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT); + + WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT); + + WMMoveWidget(panel->lowerF, 0, 60 + divThickness); + + white = WMWhiteColor(scr); + dark = WMDarkGrayColor(scr); + + panel->sampleT = WMCreateTextField(panel->upperF); + WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50); + WMMoveWidget(panel->sampleT, 10, 10); + WMSetTextFieldText(panel->sampleT, _("The quick brown fox jumps over the lazy dog")); + + font = WMBoldSystemFontOfSize(scr, 12); + + panel->famL = WMCreateLabel(panel->lowerF); + WMSetWidgetBackgroundColor(panel->famL, dark); + WMSetLabelText(panel->famL, _("Family")); + WMSetLabelFont(panel->famL, font); + WMSetLabelTextColor(panel->famL, white); + WMSetLabelRelief(panel->famL, WRSunken); + WMSetLabelTextAlignment(panel->famL, WACenter); + + panel->famLs = WMCreateList(panel->lowerF); + WMSetListAction(panel->famLs, familyClick, panel); + + panel->typL = WMCreateLabel(panel->lowerF); + WMSetWidgetBackgroundColor(panel->typL, dark); + WMSetLabelText(panel->typL, _("Typeface")); + WMSetLabelFont(panel->typL, font); + WMSetLabelTextColor(panel->typL, white); + WMSetLabelRelief(panel->typL, WRSunken); + WMSetLabelTextAlignment(panel->typL, WACenter); + + panel->typLs = WMCreateList(panel->lowerF); + WMSetListAction(panel->typLs, typefaceClick, panel); + + panel->sizL = WMCreateLabel(panel->lowerF); + WMSetWidgetBackgroundColor(panel->sizL, dark); + WMSetLabelText(panel->sizL, _("Size")); + WMSetLabelFont(panel->sizL, font); + WMSetLabelTextColor(panel->sizL, white); + WMSetLabelRelief(panel->sizL, WRSunken); + WMSetLabelTextAlignment(panel->sizL, WACenter); + + panel->sizT = WMCreateTextField(panel->lowerF); + /* WMSetTextFieldAlignment(panel->sizT, WARight); */ + + panel->sizLs = WMCreateList(panel->lowerF); + WMSetListAction(panel->sizLs, sizeClick, panel); + + WMReleaseFont(font); + WMReleaseColor(white); + WMReleaseColor(dark); + + panel->setB = WMCreateCommandButton(panel->win); + WMResizeWidget(panel->setB, 70, 24); + WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5)); + WMSetButtonText(panel->setB, _("Set")); + WMSetButtonAction(panel->setB, setClickedAction, panel); + + panel->revertB = WMCreateCommandButton(panel->win); + WMResizeWidget(panel->revertB, 70, 24); + WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT - 5)); + WMSetButtonText(panel->revertB, _("Revert")); + WMSetButtonAction(panel->revertB, revertClickedAction, panel); + + WMRealizeWidget(panel->win); + + WMMapSubwidgets(panel->upperF); + WMMapSubwidgets(panel->lowerF); + WMMapSubwidgets(panel->split); + WMMapSubwidgets(panel->win); + + WMUnmapWidget(panel->revertB); + + arrangeLowerFrame(panel); + + scr->sharedFontPanel = panel; + + /* register notification observers */ + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, WMWidgetView(panel->win)); + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, WMWidgetView(panel->upperF)); + WMAddNotificationObserver(notificationObserver, panel, + WMViewSizeDidChangeNotification, WMWidgetView(panel->lowerF)); + + listFamilies(scr, panel); + + return panel; +} + +void WMFreeFontPanel(WMFontPanel * panel) +{ + if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) { + WMWidgetScreen(panel->win)->sharedFontPanel = NULL; + } + WMRemoveNotificationObserver(panel); + WMUnmapWidget(panel->win); + WMDestroyWidget(panel->win); + wfree(panel); +} + +void WMShowFontPanel(WMFontPanel * panel) +{ + WMMapWidget(panel->win); +} + +void WMHideFontPanel(WMFontPanel * panel) +{ + WMUnmapWidget(panel->win); +} + +WMFont *WMGetFontPanelFont(WMFontPanel * panel) +{ + return WMGetTextFieldFont(panel->sampleT); +} + +void WMSetFontPanelFont(WMFontPanel * panel, char *fontName) +{ + int fname_len; + FcPattern *pattern; + FcChar8 *family, *style; + double size; + + if (!isXLFD(fontName, &fname_len)) { + /* maybe its proper fontconfig and we can parse it */ + pattern = FcNameParse((FcChar8 *) fontName); + } else { + /* maybe its proper xlfd and we can convert it to an FcPattern */ + pattern = XftXlfdParse(fontName, False, False); + /*//FcPatternPrint(pattern); */ + } + + if (!pattern) + return; + + if (FcPatternGetString(pattern, FC_FAMILY, 0, &family) == FcResultMatch) + if (FcPatternGetString(pattern, FC_STYLE, 0, &style) == FcResultMatch) + if (FcPatternGetDouble(pattern, "pixelsize", 0, &size) == FcResultMatch) + setFontPanelFontName(panel, (char *)family, (char *)style, size); + + FcPatternDestroy(pattern); +} + +void WMSetFontPanelAction(WMFontPanel * panel, WMAction2 * action, void *data) +{ + panel->action = action; + panel->data = data; +} + +static void arrangeLowerFrame(FontPanel * panel) +{ + int width = WMWidgetWidth(panel->lowerF) - 55 - 30; + int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF); + int fw, tw, sw; + +#define LABEL_HEIGHT 20 + + height -= WMGetSplitViewDividerThickness(panel->split); + + height -= LABEL_HEIGHT + 8; + + fw = (125 * width) / 235; + tw = (110 * width) / 235; + sw = 55; + + WMMoveWidget(panel->famL, 10, 0); + WMResizeWidget(panel->famL, fw, LABEL_HEIGHT); + + WMMoveWidget(panel->famLs, 10, 23); + WMResizeWidget(panel->famLs, fw, height); + + WMMoveWidget(panel->typL, 10 + fw + 3, 0); + WMResizeWidget(panel->typL, tw, LABEL_HEIGHT); + + WMMoveWidget(panel->typLs, 10 + fw + 3, 23); + WMResizeWidget(panel->typLs, tw, height); + + WMMoveWidget(panel->sizL, 10 + fw + 3 + tw + 3, 0); + WMResizeWidget(panel->sizL, sw + 4, LABEL_HEIGHT); + + WMMoveWidget(panel->sizT, 10 + fw + 3 + tw + 3, 23); + WMResizeWidget(panel->sizT, sw + 4, 20); + + WMMoveWidget(panel->sizLs, 10 + fw + 3 + tw + 3, 46); + WMResizeWidget(panel->sizLs, sw + 4, height - 23); +} + +#define NUM_FIELDS 14 + +static int isXLFD(char *font, int *length_ret) +{ + int c = 0; + + *length_ret = 0; + while (*font) { + (*length_ret)++; + if (*font++ == '-') + c++; + } + + return c == NUM_FIELDS; +} + +typedef struct { + char *typeface; + WMArray *sizes; +} Typeface; + +typedef struct { + char *name; /* gotta love simplicity */ + WMArray *typefaces; +} Family; + +static int compare_int(const void *a, const void *b) +{ + int i1 = *(int *)a; + int i2 = *(int *)b; + + if (i1 < i2) + return -1; + else if (i1 > i2) + return 1; + else + return 0; +} + +static void addSizeToTypeface(Typeface * face, int size) +{ + if (size == 0) { + int j; + + for (j = 0; j < sizeof(scalableFontSizes) / sizeof(int); j++) { + size = scalableFontSizes[j]; + + if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) { + WMAddToArray(face->sizes, (void *)(uintptr_t) size); + } + } + WMSortArray(face->sizes, compare_int); + } else { + if (!WMCountInArray(face->sizes, (void *)(uintptr_t) size)) { + WMAddToArray(face->sizes, (void *)(uintptr_t) size); + WMSortArray(face->sizes, compare_int); + } + } +} + +static void addTypefaceToXftFamily(Family * fam, char *style) +{ + Typeface *face; + WMArrayIterator i; + + if (fam->typefaces) { + WM_ITERATE_ARRAY(fam->typefaces, face, i) { + if (strcmp(face->typeface, style) != 0) + continue; /* go to next interation */ + addSizeToTypeface(face, 0); + return; + } + } else { + fam->typefaces = WMCreateArray(4); + } + + face = wmalloc(sizeof(Typeface)); + memset(face, 0, sizeof(Typeface)); + + face->typeface = wstrdup(style); + face->sizes = WMCreateArray(4); + addSizeToTypeface(face, 0); + + WMAddToArray(fam->typefaces, face); +} + +/* + * families (same family name) (Hashtable of family -> array) + * registries (same family but different registries) + * + */ +static void addFontToXftFamily(WMHashTable * families, char *name, char *style) +{ + WMArrayIterator i; + WMArray *array; + Family *fam; + + array = WMHashGet(families, name); + if (array) { + WM_ITERATE_ARRAY(array, fam, i) { + if (strcmp(fam->name, name) == 0) + addTypefaceToXftFamily(fam, style); + return; + } + } + + array = WMCreateArray(8); + + fam = wmalloc(sizeof(Family)); + memset(fam, 0, sizeof(Family)); + + fam->name = wstrdup(name); + + addTypefaceToXftFamily(fam, style); + + WMAddToArray(array, fam); + + WMHashInsert(families, fam->name, array); +} + +static void listFamilies(WMScreen * scr, WMFontPanel * panel) +{ + FcObjectSet *os = 0; + FcFontSet *fs; + FcPattern *pat; + WMHashTable *families; + WMHashEnumerator enumer; + WMArray *array; + int i; + + pat = FcPatternCreate(); + os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL); + fs = FcFontList(0, pat, os); + if (!fs) { + WMRunAlertPanel(scr, panel->win, _("Error"), + _("Could not init font config library\n"), _("OK"), NULL, NULL); + return; + } + if (pat) + FcPatternDestroy(pat); + + families = WMCreateHashTable(WMStringPointerHashCallbacks); + + if (fs) { + for (i = 0; i < fs->nfont; i++) { + FcChar8 *family; + FcChar8 *style; + + if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch) + if (FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch) + addFontToXftFamily(families, (char *)family, (char *)style); + } + FcFontSetDestroy(fs); + } + + enumer = WMEnumerateHashTable(families); + + while ((array = WMNextHashEnumeratorItem(&enumer))) { + WMArrayIterator i; + Family *fam; + char buffer[256]; + WMListItem *item; + + WM_ITERATE_ARRAY(array, fam, i) { + strcpy(buffer, fam->name); + item = WMAddListItem(panel->famLs, buffer); + + item->clientData = fam; + } + + WMFreeArray(array); + } + + WMSortListItems(panel->famLs); + + WMFreeHashTable(families); +} + +static void getSelectedFont(FontPanel * panel, char buffer[], int bufsize) +{ + WMListItem *item; + Family *family; + Typeface *face; + char *size; + + item = WMGetListSelectedItem(panel->famLs); + if (!item) + return; + family = (Family *) item->clientData; + + item = WMGetListSelectedItem(panel->typLs); + if (!item) + return; + face = (Typeface *) item->clientData; + + size = WMGetTextFieldText(panel->sizT); + + snprintf(buffer, bufsize, "%s:style=%s:pixelsize=%s", family->name, face->typeface, size); + + wfree(size); +} + +static void preview(FontPanel * panel) +{ + char buffer[512]; + WMFont *font; + + getSelectedFont(panel, buffer, sizeof(buffer)); + font = WMCreateFont(WMWidgetScreen(panel->win), buffer); + if (font) { + WMSetTextFieldFont(panel->sampleT, font); + WMReleaseFont(font); + } +} + +static void familyClick(WMWidget * w, void *data) +{ + WMList *lPtr = (WMList *) w; + WMListItem *item; + Family *family; + Typeface *face; + FontPanel *panel = (FontPanel *) data; + WMArrayIterator i; + /* current typeface and size */ + char *oface = NULL; + char *osize = NULL; + int facei = -1; + int sizei = -1; + + /* must try to keep the same typeface and size for the new family */ + item = WMGetListSelectedItem(panel->typLs); + if (item) + oface = wstrdup(item->text); + + osize = WMGetTextFieldText(panel->sizT); + + item = WMGetListSelectedItem(lPtr); + family = (Family *) item->clientData; + + WMClearList(panel->typLs); + + WM_ITERATE_ARRAY(family->typefaces, face, i) { + char buffer[256]; + int top = 0; + WMListItem *fitem; + + strcpy(buffer, face->typeface); + if (strcasecmp(face->typeface, "Roman") == 0) + top = 1; + if (strcasecmp(face->typeface, "Regular") == 0) + top = 1; + if (top) + fitem = WMInsertListItem(panel->typLs, 0, buffer); + else + fitem = WMAddListItem(panel->typLs, buffer); + fitem->clientData = face; + } + + if (oface) { + facei = WMFindRowOfListItemWithTitle(panel->typLs, oface); + wfree(oface); + } + if (facei < 0) { + facei = 0; + } + WMSelectListItem(panel->typLs, facei); + typefaceClick(panel->typLs, panel); + + if (osize) { + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); + } + if (sizei >= 0) { + WMSelectListItem(panel->sizLs, sizei); + sizeClick(panel->sizLs, panel); + } + + if (osize) + wfree(osize); + + preview(panel); +} + +static void typefaceClick(WMWidget * w, void *data) +{ + FontPanel *panel = (FontPanel *) data; + WMListItem *item; + Typeface *face; + WMArrayIterator i; + char buffer[32]; + + char *osize = NULL; + int sizei = -1; + void *size; + + osize = WMGetTextFieldText(panel->sizT); + + item = WMGetListSelectedItem(panel->typLs); + face = (Typeface *) item->clientData; + + WMClearList(panel->sizLs); + + WM_ITERATE_ARRAY(face->sizes, size, i) { + if ((int)(uintptr_t) size != 0) { + sprintf(buffer, "%i", (int)(uintptr_t) size); + + WMAddListItem(panel->sizLs, buffer); + } + } + + if (osize) { + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize); + } + if (sizei < 0) { + sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12"); + } + if (sizei < 0) { + sizei = 0; + } + WMSelectListItem(panel->sizLs, sizei); + WMSetListPosition(panel->sizLs, sizei); + sizeClick(panel->sizLs, panel); + + if (osize) + wfree(osize); + + preview(panel); +} + +static void sizeClick(WMWidget * w, void *data) +{ + FontPanel *panel = (FontPanel *) data; + WMListItem *item; + + item = WMGetListSelectedItem(panel->sizLs); + WMSetTextFieldText(panel->sizT, item->text); + + WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text))); + + preview(panel); +} + +static void setFontPanelFontName(FontPanel * panel, char *family, char *style, double size) +{ + int famrow; + int stlrow; + int sz; + char asize[64]; + void *vsize; + WMListItem *item; + Family *fam; + Typeface *face; + WMArrayIterator i; + + famrow = WMFindRowOfListItemWithTitle(panel->famLs, family); + if (famrow < 0) { + famrow = 0; + return; + } + WMSelectListItem(panel->famLs, famrow); + WMSetListPosition(panel->famLs, famrow); + + WMClearList(panel->typLs); + + item = WMGetListSelectedItem(panel->famLs); + + fam = (Family *) item->clientData; + WM_ITERATE_ARRAY(fam->typefaces, face, i) { + char buffer[256]; + int top = 0; + WMListItem *fitem; + + strcpy(buffer, face->typeface); + if (strcasecmp(face->typeface, "Roman") == 0) + top = 1; + if (top) + fitem = WMInsertListItem(panel->typLs, 0, buffer); + else + fitem = WMAddListItem(panel->typLs, buffer); + fitem->clientData = face; + } + + stlrow = WMFindRowOfListItemWithTitle(panel->typLs, style); + + if (stlrow < 0) { + stlrow = 0; + return; + } + + WMSelectListItem(panel->typLs, stlrow); + + item = WMGetListSelectedItem(panel->typLs); + + face = (Typeface *) item->clientData; + + WMClearList(panel->sizLs); + + WM_ITERATE_ARRAY(face->sizes, vsize, i) { + char buffer[32]; + if ((int)(uintptr_t) vsize != 0) { + sprintf(buffer, "%i", (int)(uintptr_t) vsize); + + WMAddListItem(panel->sizLs, buffer); + } + } + + snprintf(asize, sizeof(asize) - 1, "%d", (int)(size + 0.5)); + + sz = WMFindRowOfListItemWithTitle(panel->sizLs, asize); + + if (sz < 0) { + sz = 4; + return; + } + + WMSelectListItem(panel->sizLs, sz); + sizeClick(panel->sizLs, panel); + + return; +}