Apply clang-format to source tree
[alexxy/gromacs.git] / src / programs / view / logo.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2013, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "logo.h"
40
41 #include <cstdio>
42 #include <cstdlib>
43
44 #include "gromacs/utility/arraysize.h"
45 #include "gromacs/utility/baseversion.h"
46 #include "gromacs/utility/real.h"
47 #include "gromacs/utility/smalloc.h"
48
49 #include "Xstuff.h"
50 #include "xutil.h"
51
52 typedef struct
53 {
54     int            x, y, rad;
55     unsigned long* col;
56 } t_circle;
57
58 typedef struct
59 {
60     const char*  text;
61     int          y, h;
62     XFontStruct* fnt;
63 } t_mess;
64
65 void show_logo(t_x11* x11, t_logo* logo)
66 {
67     XMapWindow(x11->disp, logo->wd.self);
68     XMapSubwindows(x11->disp, logo->wd.self);
69 }
70
71 void hide_logo(t_x11* x11, t_logo* logo)
72 {
73     XUnmapWindow(x11->disp, logo->wd.self);
74 }
75
76 static bool LogoCallBack(t_x11* x11, XEvent* event, Window /*w*/, void* data)
77 {
78     /* Assume window is 100x110 */
79     static bool bFirst = true;
80 #define CSIZE 9
81 #define NSIZE 8
82 #define OSIZE 9
83 #define HSIZE 7
84 #define YOFFS 30
85     static t_circle c[] = {
86         { 10, YOFFS + 12, CSIZE, &LIGHTGREEN }, { 20, YOFFS + 22, CSIZE, &LIGHTGREEN },
87         { 20, YOFFS + 34, OSIZE, &LIGHTRED },   { 30, YOFFS + 12, NSIZE, &LIGHTCYAN },
88         { 30, YOFFS + 2, HSIZE, &WHITE },       { 40, YOFFS + 22, CSIZE, &LIGHTGREEN },
89         { 40, YOFFS + 34, CSIZE, &LIGHTGREEN }, { 50, YOFFS + 12, CSIZE, &LIGHTGREEN },
90         { 50, YOFFS, OSIZE, &LIGHTRED },        { 60, YOFFS + 22, NSIZE, &LIGHTCYAN },
91         { 60, YOFFS + 32, HSIZE, &WHITE },      { 70, YOFFS + 12, CSIZE, &LIGHTGREEN },
92         { 80, YOFFS + 22, CSIZE, &LIGHTGREEN }, { 80, YOFFS + 34, OSIZE, &LIGHTRED },
93         { 90, YOFFS + 12, NSIZE, &LIGHTCYAN },  { 90, YOFFS + 2, HSIZE, &WHITE },
94         { 100, YOFFS + 22, CSIZE, &LIGHTGREEN }
95     };
96     static int lines[] = { 0, 1, 1, 2,  1, 3,  3,  4,  3,  5,  5,  6,  5,  7,  7,  8,
97                            7, 9, 9, 10, 9, 11, 11, 12, 12, 13, 12, 14, 14, 15, 14, 16 };
98 #define COFFS 70
99     static t_mess Mess[] = { { "GROMACS", 0, 20, nullptr },
100                              { nullptr, 16, 9, nullptr },
101                              { "Copyright (c) 1991-2013", COFFS + 2, 9, nullptr },
102                              { "D.v.d.Spoel, E.Lindahl, B.Hess", COFFS + 11, 9, nullptr },
103                              { "& Groningen University ", COFFS + 20, 9, nullptr },
104                              { "click to dismiss", COFFS + 31, 8, nullptr } };
105 #define NMESS asize(Mess)
106     int        i;
107     t_logo*    logo;
108     t_windata* wd;
109
110     logo = (t_logo*)data;
111     wd   = &(logo->wd);
112     if (bFirst)
113     {
114         const real wfac = wd->width / 110.0;
115         const real hfac = wd->height / 110.0;
116         for (i = 0; (i < asize(c)); i++)
117         {
118             c[i].x *= wfac;
119             c[i].y *= hfac;
120         }
121         Mess[1].text = gmx_version();
122         for (i = 0; (i < NMESS); i++)
123         {
124             Mess[i].y *= hfac;
125             Mess[i].h *= hfac;
126             Mess[i].fnt = (i == 0) ? logo->bigfont : (i == NMESS - 1) ? x11->font : logo->smallfont;
127         }
128         bFirst = false;
129     }
130     switch (event->type)
131     {
132         case Expose:
133             XSetForeground(x11->disp, x11->gc, WHITE);
134             XSetLineAttributes(x11->disp, x11->gc, 3, LineSolid, CapNotLast, JoinRound);
135             for (i = 0; (i < asize(lines)); i += 2)
136             {
137                 XDrawLine(x11->disp, wd->self, x11->gc, c[lines[i]].x, c[lines[i]].y,
138                           c[lines[i + 1]].x, c[lines[i + 1]].y);
139             }
140             XSetLineAttributes(x11->disp, x11->gc, 1, LineSolid, CapNotLast, JoinRound);
141             for (i = 0; (i < asize(c)); i++)
142             {
143                 XSetForeground(x11->disp, x11->gc, *(c[i].col));
144                 XFillCircle(x11->disp, wd->self, x11->gc, c[i].x, c[i].y, c[i].rad);
145             }
146             XSetForeground(x11->disp, x11->gc, BLACK);
147             XDrawRectangle(x11->disp, wd->self, x11->gc, 2, 2, wd->width - 5, wd->height - 5);
148             for (i = 0; (i < NMESS); i++)
149             {
150                 SpecialTextInRect(x11, Mess[i].fnt, wd->self, Mess[i].text, 0, Mess[i].y, wd->width,
151                                   Mess[i].h, eXCenter, eYCenter);
152             }
153             XSetForeground(x11->disp, x11->gc, x11->fg);
154             break;
155         case ButtonPress:
156             hide_logo(x11, logo);
157             return logo->bQuitOnClick;
158             break;
159         default: break;
160     }
161
162     return false;
163 }
164
165 t_logo* init_logo(t_x11* x11, Window parent, bool bQuitOnClick)
166 {
167     static const char* bfname[] = { "-b&h-lucida-bold-i-normal-sans-34-240-100-100-p-215-iso8859-1",
168                                     "-b&h-lucida-bold-i-normal-sans-26-190-100-100-p-166-iso8859-1",
169                                     "lucidasans-bolditalic-24",
170                                     "lucidasans-italic-24",
171                                     "10x20",
172                                     "fixed" };
173 #define NBF asize(bfname)
174     static const char* sfname[] = { "lucidasans-bold-18", "10x20", "fixed" };
175 #define NSF asize(sfname)
176     int           i;
177     unsigned long bg;
178     char*         newcol;
179     t_logo*       logo;
180
181     snew(logo, 1);
182     logo->bQuitOnClick = bQuitOnClick;
183     InitWin(&logo->wd, 0, 0, 360, 270, 1, "GROMACS");
184     bg = LIGHTGREY;
185     if ((newcol = std::getenv("GMX_LOGO_COLOR")) != nullptr)
186     {
187         GetNamedColor(x11, newcol, &bg);
188     }
189     logo->wd.self = XCreateSimpleWindow(x11->disp, parent, logo->wd.x, logo->wd.y, logo->wd.width,
190                                         logo->wd.height, logo->wd.bwidth, WHITE, bg);
191     for (i = 0, logo->bigfont = nullptr; (i < NBF); i++)
192     {
193         if ((logo->bigfont = XLoadQueryFont(x11->disp, bfname[i])) != nullptr)
194         {
195             break;
196         }
197     }
198     if (i == NBF)
199     {
200         std::perror(bfname[i - 1]);
201         std::exit(1);
202     }
203 #ifdef DEBUG
204     std::fprintf(stderr, "Big Logofont: %s\n", bfname[i]);
205 #endif
206     for (i = 0, logo->smallfont = nullptr; (i < NSF); i++)
207     {
208         if ((logo->smallfont = XLoadQueryFont(x11->disp, sfname[i])) != nullptr)
209         {
210             break;
211         }
212     }
213     if (i == NSF)
214     {
215         std::perror(sfname[i - 1]);
216         std::exit(1);
217     }
218 #ifdef DEBUG
219     std::fprintf(stderr, "Small Logofont: %s\n", sfname[i]);
220 #endif
221     x11->RegisterCallback(x11, logo->wd.self, parent, LogoCallBack, logo);
222     x11->SetInputMask(x11, logo->wd.self, ButtonPressMask | ExposureMask);
223
224     return logo;
225 }
226
227 void done_logo(t_x11* x11, t_logo* logo)
228 {
229     x11->UnRegisterCallback(x11, logo->wd.self);
230 }