1 /*******************************************************************************
2 *                         Goggles Music Manager                                *
3 ********************************************************************************
4 *           Copyright (C) 2009-2021 by Sander Jansen. All Rights Reserved      *
5 *                               ---                                            *
6 * This program is free software: you can redistribute it and/or modify         *
7 * it under the terms of the GNU General Public License as published by         *
8 * the Free Software Foundation, either version 3 of the License, or            *
9 * (at your option) any later version.                                          *
10 *                                                                              *
11 * This program is distributed in the hope that it will be useful,              *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of               *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                *
14 * GNU General Public License for more details.                                 *
15 *                                                                              *
16 * You should have received a copy of the GNU General Public License            *
17 * along with this program.  If not, see http://www.gnu.org/licenses.           *
18 ********************************************************************************/
19 #include "gmdefs.h"
20 #include "GMList.h"
21 #include "GMFontDialog.h"
22 
23 FXDEFMAP(GMFontDialog) GMFontDialogMap[]={
24   FXMAPFUNC(SEL_UPDATE,GMFontDialog::ID_PITCH,GMFontDialog::onUpdPitch),
25   FXMAPFUNC(SEL_UPDATE,GMFontDialog::ID_SCALABLE,GMFontDialog::onUpdScalable),
26   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_PITCH,GMFontDialog::onCmdPitch),
27   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_SCALABLE,GMFontDialog::onCmdScalable),
28   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_FAMILY,GMFontDialog::onCmdFamily),
29   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_STYLE,GMFontDialog::onCmdStyle),
30   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_SIZE,GMFontDialog::onCmdSize),
31   FXMAPFUNC(SEL_COMMAND,GMFontDialog::ID_SIZE_TEXT,GMFontDialog::onCmdSizeText)
32   };
33 
FXIMPLEMENT(GMFontDialog,FXDialogBox,GMFontDialogMap,ARRAYNUMBER (GMFontDialogMap))34 FXIMPLEMENT(GMFontDialog,FXDialogBox,GMFontDialogMap,ARRAYNUMBER(GMFontDialogMap))
35 
36 
37 GMFontDialog::GMFontDialog(FXApp * a,const FXString& name,FXuint opts,FXint x,FXint y,FXint w,FXint h) :
38   FXDialogBox(a,name,opts,x,y,w,h,3,3,3,3) {
39   }
40 
GMFontDialog(FXWindow * o,const FXString & name,FXuint opts,FXint x,FXint y,FXint w,FXint h)41 GMFontDialog::GMFontDialog(FXWindow* o,const FXString& name,FXuint opts,FXint x,FXint y,FXint w,FXint h) :
42   FXDialogBox(o,name,opts,x,y,w,h,4,4,4,4) {
43   GMScrollFrame *sunken;
44 //  FXVerticalFrame * frm;
45 
46   FXHorizontalFrame *closebox=new FXHorizontalFrame(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,0,0,0,0,0,0,2,2);
47   new GMButton(closebox," &Accept",nullptr,this,FXDialogBox::ID_ACCEPT,BUTTON_INITIAL|BUTTON_DEFAULT|LAYOUT_RIGHT|FRAME_RAISED|FRAME_THICK,0,0,0,0, 15,15);
48   new GMButton(closebox," &Cancel ",nullptr,this,FXDialogBox::ID_CANCEL,BUTTON_DEFAULT|LAYOUT_RIGHT|FRAME_RAISED|FRAME_THICK,0,0,0,0, 15,15);
49 
50   FXVerticalFrame * main = new FXVerticalFrame(this,LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0,0,0);
51 //frm=new FXVerticalFrame(main,LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK|LAYOUT_BOTTOM,0,0,0,0,0,0,0,0);
52   sunken=new GMScrollFrame(main);
53   sunken->setLayoutHints(LAYOUT_BOTTOM|LAYOUT_FILL_X|LAYOUT_FILL_Y);
54 
55   FXScrollWindow *scrollwindow=new FXScrollWindow(sunken,LAYOUT_FILL_X|LAYOUT_FILL_Y);
56   GMScrollArea::replaceScrollbars(scrollwindow);
57   preview=new FXLabel(scrollwindow,"ABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n0123456789",nullptr,LAYOUT_CENTER_X|LAYOUT_CENTER_Y);
58   preview->setBackColor(getApp()->getBackColor());
59 //  new FXLabel(main,"Preview:",nullptr,LAYOUT_BOTTOM);
60 
61   FXHorizontalFrame * filterframe = new FXHorizontalFrame(main,LAYOUT_FILL_X|LAYOUT_BOTTOM,0,0,0,0,0,0,3,3,0,0);
62   new FXLabel(filterframe,"Pitch:",nullptr,LABEL_NORMAL|LAYOUT_CENTER_Y,0,0,0,0);
63   pitchlist = new GMListBox(filterframe,this,ID_PITCH);
64   pitchlist->appendItem("Any");
65   pitchlist->appendItem("Fixed",nullptr,(void*)(FXuval)FXFont::Fixed);
66   pitchlist->appendItem("Variable",nullptr,(void*)(FXuval)FXFont::Variable);
67   pitchlist->setNumVisible(3);
68 
69   new FXLabel(filterframe,"  Type:",nullptr,LABEL_NORMAL|LAYOUT_CENTER_Y);
70   scalelist = new GMListBox(filterframe,this,ID_SCALABLE);
71   scalelist->appendItem("Any");
72   scalelist->appendItem("Scalable",nullptr,(void*)(FXuval)FXFont::Scalable);
73   scalelist->setNumVisible(2);
74 
75   FXHorizontalFrame * input = new FXHorizontalFrame(main,LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0);
76 
77   FXVerticalFrame * sizeframe = new FXVerticalFrame(input,LAYOUT_RIGHT|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0,0,0);
78   new FXLabel(sizeframe,"Size:",nullptr,LABEL_NORMAL,0,0,0,0,0,0);
79 
80   FXVerticalFrame * sizeinputframe = new FXVerticalFrame(sizeframe,LAYOUT_RIGHT|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0);
81   sizefield=new GMTextField(sizeinputframe,3,this,ID_SIZE_TEXT,TEXTFIELD_NORMAL|TEXTFIELD_INTEGER|LAYOUT_FILL_X);
82   sunken=new GMScrollFrame(sizeinputframe);
83   sizelist=new GMList(sunken,this,ID_SIZE,LAYOUT_FILL_Y|LAYOUT_FILL_X|LIST_SINGLESELECT);
84 
85   FXHorizontalFrame * mainframe = new FXHorizontalFrame(input,LAYOUT_LEFT|LAYOUT_FILL_Y|LAYOUT_FILL_X,0,0,0,0,0,0,0,0);
86   FXSpring * familyframe = new FXSpring(mainframe,LAYOUT_FILL_X|LAYOUT_FILL_Y,4,0,0,0,0,0,0,0,0,0,0,0);
87   new FXLabel(familyframe,"Family:",nullptr,LABEL_NORMAL,0,0,0,0);
88   sunken=new GMScrollFrame(familyframe);
89   familylist = new GMList(sunken,this,ID_FAMILY,LAYOUT_FILL_Y|LAYOUT_FILL_X|LIST_BROWSESELECT);
90   familylist->setSortFunc(FXList::ascending);
91 
92   FXSpring * styleframe  = new FXSpring(mainframe,LAYOUT_FILL_X|LAYOUT_FILL_Y,3,0,0,0,0,0,0,0,0,0,0,0);
93   new FXLabel(styleframe,"Style:",nullptr,LABEL_NORMAL,0,0,0,0);
94   sunken=new GMScrollFrame(styleframe);
95   stylelist=new GMList(sunken,this,ID_STYLE,LAYOUT_FILL_Y|LAYOUT_FILL_X|LIST_BROWSESELECT);
96   stylelist->setSortFunc(FXList::ascending);
97 
98   selected = getApp()->getNormalFont()->getActualFontDesc();
99   selected.flags|=FXFont::Scalable;
100   }
101 
~GMFontDialog()102 GMFontDialog::~GMFontDialog(){
103   }
104 
105 
setFontDesc(const FXFontDesc & fontdesc)106 void GMFontDialog::setFontDesc(const FXFontDesc& fontdesc){
107   selected=fontdesc;
108   }
109 
getFontDesc() const110 const FXFontDesc& GMFontDialog::getFontDesc() const {
111   return selected;
112   }
113 
114 
create()115 void GMFontDialog::create() {
116   FXDialogBox::create();
117   listFontFamily();
118   listFontStyle();
119   listFontSize();
120   }
121 
122 // Preview
previewFont()123 void GMFontDialog::previewFont(){
124   FXFont *old;
125 
126   // Save old font
127   old=previewfont;
128 
129   // Get new font
130   previewfont=new FXFont(getApp(),selected);
131 
132   // Realize new font
133   previewfont->create();
134 
135   // Set new font
136   preview->setFont(previewfont);
137 
138   // Delete old font
139   delete old;
140   }
141 
142 
listFontFamily()143 void GMFontDialog::listFontFamily(){
144   FXFontDesc * fonts=nullptr;
145   FXuint numfonts,f;
146   FXint lastitem=-1,selindex=-1;
147   FXString face,family,pfamily;
148 
149   familylist->clearItems();
150   if (FXFont::listFonts(fonts,numfonts,FXString::null,0,0,0,selected.encoding,selected.flags)) {
151     for(f=0;f<numfonts;f++){
152       family=FXString(fonts[f].face).before('[').trimEnd();
153       if (pfamily==family && lastitem>=0) {
154         familylist->setItemText(lastitem,fonts[f-1].face);
155         lastitem=familylist->appendItem(fonts[f].face,nullptr,(void*)(FXuval)fonts[f].flags);
156         }
157       else {
158         lastitem=familylist->appendItem(family,nullptr,(void*)(FXuval)fonts[f].flags);
159         }
160       pfamily.adopt(family);
161       if(compare(selected.face,fonts[f].face)==0) selindex=f;
162       }
163     if(selindex==-1) selindex=0;
164     if(0<familylist->getNumItems()){
165       familylist->setCurrentItem(selindex);
166       familylist->makeItemVisible(selindex);
167       fxstrlcpy(selected.face,familylist->getItemText(selindex).text(),sizeof(selected.face));
168       }
169     FXFREE(&fonts);
170     }
171   familylist->sortItems();
172   }
173 
listFontStyle()174 void GMFontDialog::listFontStyle(){
175   FXFontDesc * fonts=nullptr;
176   FXint selindex=-1;
177   FXuint numfonts,f;
178   FXushort wi,ww,lastwi=0,lastww=0,sl,lastsl=0;
179   const FXchar *wgt=nullptr,*slt=nullptr,*wid=nullptr;
180   stylelist->clearItems();
181   if (FXFont::listFonts(fonts,numfonts,selected.face,0,0,0/*selected.weight,selected.slant,selected.setwidth*/,selected.encoding,selected.flags)) {
182     for(f=0;f<numfonts;f++){
183       ww=fonts[f].weight;
184       sl=fonts[f].slant;
185       wi=fonts[f].setwidth;
186       if(ww!=lastww || sl!=lastsl || wi!=lastwi){
187         if(wi!=lastwi){
188           switch(wi){
189             case FXFont::UltraCondensed : wid=tr("Ultra Condensed"); break;
190             case FXFont::ExtraCondensed : wid=tr("Extra Condensed"); break;
191             case FXFont::Condensed      : wid=tr("Condensed"); break;
192             case FXFont::SemiCondensed  : wid=tr("Semi Condensed"); break;
193             case FXFont::NonExpanded    : wid=nullptr; break;
194             case FXFont::SemiExpanded   : wid=tr("Semi Expanded"); break;
195             case FXFont::Expanded       : wid=tr("Expanded"); break;
196             case FXFont::ExtraExpanded  : wid=tr("Extra Expanded"); break;
197             case FXFont::UltraExpanded  : wid=tr("Ultra Expanded"); break;
198             default                     : wid=nullptr; break;
199             }
200           lastwi=wi;
201           }
202         if(ww!=lastww){
203           switch(ww){
204             case FXFont::Thin       : wgt=tr("Thin"); break;
205             case FXFont::ExtraLight : wgt=tr("Extra Light"); break;
206             case FXFont::Light      : wgt=tr("Light"); break;
207             case FXFont::Normal     : wgt=nullptr; break;
208             case FXFont::Medium     : wgt=tr("Medium"); break;
209             case FXFont::DemiBold   : wgt=tr("Demibold"); break;
210             case FXFont::Bold       : wgt=tr("Bold"); break;
211             case FXFont::ExtraBold  : wgt=tr("Extra Bold"); break;
212             case FXFont::Black      : wgt=tr("Heavy"); break;
213             default                 : wgt=nullptr; break;
214             }
215           lastww=ww;
216           }
217         if (sl!=lastsl) {
218           switch(sl){
219             case FXFont::ReverseOblique : slt=tr("Reverse Oblique"); break;
220             case FXFont::ReverseItalic  : slt=tr("Reverse Italic"); break;
221             case FXFont::Straight       : slt=nullptr; break;
222             case FXFont::Italic         : slt=tr("Italic"); break;
223             case FXFont::Oblique        : slt=tr("Oblique"); break;
224             default                     : slt=nullptr; break;
225             }
226           lastsl=sl;
227           }
228 
229         FXuint style=FXRGB((FXuchar)ww,(FXuchar)sl,(FXuchar)wi);
230         if (wgt && slt && wid)
231           stylelist->appendItem(FXString::value("%s %s %s",wgt,wid,slt),nullptr,(void*)(FXuval)style);
232         else if (wgt && slt)
233           stylelist->appendItem(FXString::value("%s %s",wgt,slt),nullptr,(void*)(FXuval)style);
234         else if (wgt && wid)
235           stylelist->appendItem(FXString::value("%s %s",wgt,wid),nullptr,(void*)(FXuval)style);
236         else if (wid && slt)
237           stylelist->appendItem(FXString::value("%s %s",wid,slt),nullptr,(void*)(FXuval)style);
238         else if (slt)
239           stylelist->appendItem(tr(slt),nullptr,(void*)(FXuval)style);
240         else if (wgt)
241           stylelist->appendItem(tr(wgt),nullptr,(void*)(FXuval)style);
242         else if (wid)
243           stylelist->appendItem(tr(wid),nullptr,(void*)(FXuval)style);
244         else
245           stylelist->appendItem(tr("Normal"),nullptr,(void*)(FXuval)style);
246 
247         if (ww==selected.weight && sl==selected.slant && wi==selected.setwidth) {
248           selindex=stylelist->getNumItems()-1;
249           }
250         }
251       }
252     FXFREE(&fonts);
253     if(selindex==-1) selindex=0;
254     if(0<stylelist->getNumItems()){
255       stylelist->setCurrentItem(selindex);
256       FXuint style=(FXuint)(FXuval)stylelist->getItemData(selindex);
257       selected.weight=FXREDVAL(style);
258       selected.slant=FXGREENVAL(style);
259       selected.setwidth=FXBLUEVAL(style);
260       stylelist->makeItemVisible(selindex);
261       //stylelist->sortItems();
262       }
263     }
264   }
265 
266 
listFontSize()267 void GMFontDialog::listFontSize(){
268   const FXuint sizeint[]={60,80,90,100,110,120,140,160,200,240,300,360,420,480,640,720};
269   FXFontDesc *fonts;
270   FXuint numfonts,f,s,lasts;
271   FXint selindex=-1;
272   sizelist->clearItems();
273   sizefield->setText(FXString::null);
274   FXString string;
275   if(FXFont::listFonts(fonts,numfonts,selected.face,selected.weight,selected.slant,selected.setwidth,selected.encoding,selected.flags)){
276     FXASSERT(0<numfonts);
277     lasts=0;
278     if(fonts[0].flags&FXFont::Scalable){
279       FXuint style=sizelist->getListStyle();
280       style&=~LIST_BROWSESELECT;
281       style|=LIST_SINGLESELECT;
282       sizelist->setListStyle(style);
283       for(f=0; f<ARRAYNUMBER(sizeint); f++){
284         s=sizeint[f];
285         string.format("%g",0.1*s);
286         sizelist->appendItem(string,nullptr,(void*)(FXuval)s);
287         if(selected.size == s) selindex=sizelist->getNumItems()-1;
288         }
289       }
290     else{
291       FXuint style=sizelist->getListStyle();
292       style&=~LIST_SINGLESELECT;
293       style|=LIST_BROWSESELECT;
294       sizelist->setListStyle(style);
295       for(f=0; f<numfonts; f++){
296         s=fonts[f].size;
297         if(s!=lasts){
298           string.format("%.1f",0.1*s);
299           sizelist->appendItem(string,nullptr,(void*)(FXuval)s);
300           if(selected.size==s) selindex=sizelist->getNumItems()-1;
301           lasts=s;
302           }
303         }
304       }
305     if(selindex==-1) selindex=0;
306     if(0<sizelist->getNumItems()){
307       sizelist->selectItem(selindex);
308       sizelist->makeItemVisible(selindex);
309       sizefield->setText(sizelist->getItemText(selindex));
310       selected.size=(FXuint)(FXuval)sizelist->getItemData(selindex);
311       }
312     FXFREE(&fonts);
313     }
314   }
315 
onCmdFamily(FXObject *,FXSelector,void * ptr)316 long GMFontDialog::onCmdFamily(FXObject*,FXSelector,void* ptr){
317   fxstrlcpy(selected.face,familylist->getItemText((FXint)(FXival)ptr).text(),sizeof(selected.face));
318   listFontStyle();
319   listFontSize();
320   previewFont();
321   return 1;
322   }
323 
onCmdStyle(FXObject *,FXSelector,void * ptr)324 long GMFontDialog::onCmdStyle(FXObject*,FXSelector,void* ptr){
325   FXuint style=(FXuint)(FXuval)stylelist->getItemData((FXint)(FXival)ptr);
326   selected.weight=FXREDVAL(style);
327   selected.slant=FXGREENVAL(style);
328   selected.setwidth=FXBLUEVAL(style);
329   listFontSize();
330   previewFont();
331   return 1;
332   }
333 
onCmdSize(FXObject *,FXSelector,void * ptr)334 long GMFontDialog::onCmdSize(FXObject*,FXSelector,void*ptr){
335   selected.size=(FXuint)(FXuval)sizelist->getItemData((FXint)(FXival)ptr);
336   sizefield->setText(sizelist->getItemText((FXint)(FXival)ptr));
337   previewFont();
338   return 1;
339   }
onCmdSizeText(FXObject *,FXSelector,void *)340 long GMFontDialog::onCmdSizeText(FXObject*,FXSelector,void*){
341   selected.size=(FXuint)(10.0f*sizefield->getText().toFloat());
342   if(selected.size<60) selected.size=60;
343   if(selected.size>2400) selected.size=2400;
344   previewFont();
345   return 1;
346   }
347 
348 
349 // Changed pitch
onCmdPitch(FXObject *,FXSelector,void * ptr)350 long GMFontDialog::onCmdPitch(FXObject*,FXSelector,void*ptr){
351   FXint index=(FXint)(FXival)ptr;
352   selected.flags&=~(FXFont::Fixed|FXFont::Variable);
353   selected.flags|=(FXuint)(FXuval)pitchlist->getItemData(index);
354   listFontFamily();
355   listFontStyle();
356   listFontSize();
357   previewFont();
358   return 1;
359   }
360 
onUpdPitch(FXObject * sender,FXSelector,void *)361 long GMFontDialog::onUpdPitch(FXObject*sender,FXSelector,void*){
362   FXint value=(selected.flags&FXFont::Fixed) ? 1 : (selected.flags&FXFont::Variable) ? 2 : 0;
363   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),&value);
364   return 1;
365   }
366 
367 // Changed pitch
onCmdScalable(FXObject *,FXSelector,void * ptr)368 long GMFontDialog::onCmdScalable(FXObject*,FXSelector,void*ptr){
369   FXint index=(FXint)(FXival)ptr;
370   selected.flags&=~(FXFont::Scalable);
371   selected.flags|=(FXuint)(FXuval)scalelist->getItemData(index);
372   listFontFamily();
373   listFontStyle();
374   listFontSize();
375   previewFont();
376   return 1;
377   }
378 
onUpdScalable(FXObject * sender,FXSelector,void *)379 long GMFontDialog::onUpdScalable(FXObject*sender,FXSelector,void*){
380   FXint value=(selected.flags&FXFont::Scalable) ? 1 : 0;
381   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),&value);
382   return 1;
383   }
384