diff --git a/debian/celestia-gtk.install b/debian/celestia-gtk.install index 2ac59b0e90..2f3ab797b0 100644 --- a/debian/celestia-gtk.install +++ b/debian/celestia-gtk.install @@ -1,5 +1,5 @@ usr/bin/celestia-gtk usr/share/celestia/celestiaui.xml usr/share/applications/celestia-gtk.desktop -usr/share/metainfo/space.celestia.celestia_gtk.metainfo.xml +usr/share/metainfo/space.celestiaproject.Celestia-gtk.metainfo.xml usr/share/man/man1/celestia-gtk.1 diff --git a/debian/celestia-qt5.install b/debian/celestia-qt5.install index fa99c1f924..e5d3ab7c46 100644 --- a/debian/celestia-qt5.install +++ b/debian/celestia-qt5.install @@ -1,4 +1,4 @@ usr/bin/celestia-qt5 usr/share/applications/celestia-qt5.desktop -usr/share/metainfo/space.celestia.celestia_qt5.metainfo.xml +usr/share/metainfo/space.celestiaproject.Celestia-qt5.metainfo.xml usr/share/man/man1/celestia-qt5.1 diff --git a/po/bg.po b/po/bg.po index cee3044adf..06cfddf180 100644 --- a/po/bg.po +++ b/po/bg.po @@ -2,11 +2,11 @@ # Copyright (C) YEAR Celestia Development Team # This file is distributed under the same license as the celestia package. # FIRST AUTHOR , YEAR. -# +# # Translators: -# Hleb Valoshka <375gnu@gmail.com>, 2021 -# Georgi Georgiev (Жоро) , 2023 -# +# Hleb Valoshka <375gnu@gmail.com>, 2023 +# Georgi Georgiev (RacerBG) , 2024 +# #, fuzzy msgid "" msgstr "" @@ -14,13 +14,12 @@ msgstr "" "Report-Msgid-Bugs-To: team@celestiaproject.space\n" "POT-Creation-Date: 2023-12-17 11:09+0100\n" "PO-Revision-Date: 2018-11-02 18:33+0000\n" -"Last-Translator: Georgi Georgiev (Жоро) , 2023\n" -"Language-Team: Bulgarian (https://app.transifex.com/celestia/teams/93131/" -"bg/)\n" -"Language: bg\n" +"Last-Translator: Georgi Georgiev (RacerBG) , 2024\n" +"Language-Team: Bulgarian (https://app.transifex.com/celestia/teams/93131/bg/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/celastro/date.cpp:486 @@ -31,27 +30,25 @@ msgstr "ЛЧВ" msgid "STD" msgstr "СЧВ" -#. #. // Put AbsMag = avgAbsMag for Add-ons without AbsMag entry #. for (int i = 0; i < nDSOs; ++i) #. { #. if(DSOs[i]->getAbsoluteMagnitude() == DSO_DEFAULT_ABS_MAGNITUDE) #. DSOs[i]->setAbsoluteMagnitude((float)avgAbsMag); #. } -#. #: ../src/celengine/dsodb.cpp:333 msgid "Loaded {} deep space objects\n" -msgstr "Заредени са {} обекти от дълбокия космос\n" +msgstr "Заредени са {} обекта от дълбокия космос\n" #: ../src/celengine/galaxy.cpp:95 #, c-format msgid "Galaxy (Hubble type: %s)" -msgstr "Галактика (спецификация на Хъбъл: %s)" +msgstr "Галактика (тип: %s)" #: ../src/celengine/globular.cpp:70 #, c-format, qt-format msgid "Globular (core radius: %4.2f', King concentration: %4.2f)" -msgstr "Кълбовиден (размер на ядрото: %4.2f', плътност: %4.2f)" +msgstr "Кълбовиден (радиус на ядрото: %4.2f', плътност: %4.2f)" #: ../src/celengine/meshmanager.cpp:451 msgid "Loading model: {}\n" @@ -59,22 +56,21 @@ msgstr "Зареждане на модел: {}\n" #: ../src/celengine/meshmanager.cpp:466 msgid "Unknown model format '{}'\n" -msgstr "" +msgstr "Неизвестен формат на модела „{}“\n" #: ../src/celengine/meshmanager.cpp:472 msgid "Error loading model '{}'\n" -msgstr "Грешка при зареждане на модел „{}“\n" +msgstr "Грешка при зареждане на модела „{}“\n" #. Display some statics for the model #: ../src/celengine/meshmanager.cpp:493 msgid "" " Model statistics: {} vertices, {} primitives, {} materials ({} unique)\n" -msgstr "" -"Данни за модела: {} върхове, {} примитиви, {} материали ({} уникални)\n" +msgstr "Данни за модела: {} върхове, {} примитиви, {} материали ({} уникални)\n" #: ../src/celengine/modelgeometry.cpp:186 msgid "Mesh index {} is higher than VBO count {}!" -msgstr "" +msgstr "Индексът на мрежата {} е по-голям от броя на VBO {}!" #: ../src/celengine/nebula.cpp:33 msgid "Nebula" @@ -86,39 +82,39 @@ msgstr "Разсеян куп" #: ../src/celengine/solarsys.cpp:104 msgid "Error in .ssc file (line {}): {}\n" -msgstr "Грешка в „.ssc“ файла (линия {}): {}\n" +msgstr "Грешка в .ssc файла (линия {}): {}\n" #: ../src/celengine/solarsys.cpp:745 msgid "Ring system needs inner and outer radii.\n" -msgstr "" +msgstr "Пръстеновата система се нуждае от вътрешен и външен радиус.\n" #: ../src/celengine/solarsys.cpp:837 msgid "Invalid SemiAxes value for object {}: [{}, {}, {}]\n" -msgstr "" +msgstr "Невалидна стойност на полуоста за обекта {}: [{}, {}, {}]\n" #: ../src/celengine/solarsys.cpp:872 msgid "Invalid Oblateness value for object {}: {}\n" -msgstr "" +msgstr "Невалидна стойност на сплеснатост за обекта {}: {}\n" #: ../src/celengine/solarsys.cpp:926 msgid "Incorrect GeomAlbedo value: {}\n" -msgstr "Неправилна стойност на „GeomAlbedo“: {}\n" +msgstr "Неправилна стойност на геометричното албедо: {}\n" #: ../src/celengine/solarsys.cpp:935 msgid "Incorrect Reflectivity value: {}\n" -msgstr "Неправилна стойност на „Reflectivity“: {}\n" +msgstr "Неправилна стойност на отражателната способност: {}\n" #: ../src/celengine/solarsys.cpp:943 msgid "Incorrect BondAlbedo value: {}\n" -msgstr "Неправилна стойност на „BondAlbedo“: {}\n" +msgstr "Неправилна стойност на сферичното албедо: {}\n" #: ../src/celengine/solarsys.cpp:985 msgid "Atmosphere must be an associative array.\n" -msgstr "" +msgstr "Атмосферата трябва да е асоциативен масив.\n" #: ../src/celengine/solarsys.cpp:994 msgid "Rings must be an associative array.\n" -msgstr "" +msgstr "Пръстените трябва да са асоциативен масив.\n" #: ../src/celengine/solarsys.cpp:1205 ../src/celengine/solarsys.cpp:1262 #, c-format @@ -140,7 +136,7 @@ msgstr "неточно местоположение" #: ../src/celengine/stardb.cpp:346 msgid "Error in .stc file (line {}): {}\n" -msgstr "Грешка в „.stc“ файла (линия {}): {}\n" +msgstr "Грешка в .stc файла (линия {}): {}\n" #: ../src/celengine/stardb.cpp:760 msgid "Bad spectral type in star database, star #{}\n" @@ -152,20 +148,20 @@ msgstr "{} звезди в двоичната база от данни\n" #: ../src/celengine/stardb.cpp:1071 msgid "Bad header for cross index\n" -msgstr "Неточна заглавка за кръстосаното индексиране\n" +msgstr "Неточна заглавка за кръстосания индекс\n" #: ../src/celengine/stardb.cpp:1079 msgid "Bad version for cross index\n" -msgstr "Неточна версия за кръстосаното индексиране\n" +msgstr "Неточна версия за кръстосания индекс\n" #: ../src/celengine/stardb.cpp:1096 msgid "Loading cross index failed\n" -msgstr "Зареждането на кръстосаното индексиране се провали\n" +msgstr "Зареждането на кръстосания индекс се провали\n" #: ../src/celengine/stardb.cpp:1107 -#, fuzzy msgid "Loading cross index failed - unexpected EOF\n" -msgstr "Зареждането на кръстосаното индексиране дава грешка при {}\n" +msgstr "" +"Зареждането на кръстосания индекс е неуспешно – неочакван край на файла\n" #: ../src/celengine/stardb.cpp:1137 msgid "Total star count: {}\n" @@ -218,27 +214,23 @@ msgstr "Създаване на обикновена текстура: {}х{}\n" #: ../src/celephem/sampfile.cpp:46 msgid "Skipping out-of-order samples in {}.\n" -msgstr "" +msgstr "Пропускане на неподредените примери в {}.\n" #: ../src/celephem/sampfile.cpp:58 -#, fuzzy msgid "No samples found in sample file {}.\n" -msgstr "Грешка при отваряне на изображение {}.\n" +msgstr "Няма намерени примери в примерния файл {}.\n" #: ../src/celephem/sampfile.cpp:67 -#, fuzzy msgid "Error reading sample file {}.\n" -msgstr "Грешка при четене на файла с фаворити {}.\n" +msgstr "Грешка при четене на примерния файл {}.\n" #: ../src/celephem/sampfile.cpp:74 -#, fuzzy msgid "Error opening ASCII sample file {}.\n" -msgstr "Грешка при отваряне на изображение {}.\n" +msgstr "Грешка при отваряне на примерния файл ASCII {}.\n" #: ../src/celephem/sampfile.cpp:81 -#, fuzzy msgid "Error finding data in ASCII sample file {}.\n" -msgstr "Грешка при отваряне на астеризмите {}.\n" +msgstr "Грешка при четене на данните в примерния файл ASCII {}.\n" #: ../src/celephem/samporbit.cpp:624 ../src/tools/xyzv2bin/bin2xyzv.cpp:35 msgid "Error reading header of {}.\n" @@ -246,31 +238,27 @@ msgstr "Грешка при четене на заглавката от {}.\n" #: ../src/celephem/samporbit.cpp:630 ../src/tools/xyzv2bin/bin2xyzv.cpp:41 msgid "Bad binary xyzv file {}.\n" -msgstr "Неточен бинарен файл „xyzv“ {}.\n" +msgstr "Неточен двоичен файл xyzv {}.\n" #: ../src/celephem/samporbit.cpp:638 -#, fuzzy msgid "Unsupported byte order {}, expected {} in {}.\n" -msgstr "Неподдържан байтов ред {}, очакван {}.\n" +msgstr "Неподдържан ред на байтовете {}, очакван {} в {}.\n" #: ../src/celephem/samporbit.cpp:647 -#, fuzzy msgid "Unsupported digits number {}, expected {} in {}.\n" -msgstr "Неподдържано число {}, очаквано {}.\n" +msgstr "Неподдържан брой числа {}, очакван {} в {}.\n" #: ../src/celephem/samporbit.cpp:656 msgid "Invalid record count {} in {}.\n" -msgstr "" +msgstr "Невалиден брой на записите {} в {}.\n" #: ../src/celephem/samporbit.cpp:712 -#, fuzzy msgid "Error opening binary sample file {}.\n" -msgstr "Грешка при отваряне на изображение {}.\n" +msgstr "Грешка при отваряне на двоичния примерен файл {}.\n" #: ../src/celephem/samporbit.cpp:718 -#, fuzzy msgid "Could not read XYZV binary file {}.\n" -msgstr "Изображението не може да бъде запазено." +msgstr "Двоичният файл XYZV не може да бъде прочетен {}.\n" #: ../src/celestia/celestiacore.cpp:110 ../src/celestia/scriptmenu.cpp:108 #: ../src/celscript/lua/luascript.cpp:173 @@ -384,22 +372,19 @@ msgstr "Продължи" #: ../src/celestia/celestiacore.cpp:1118 msgid "Star color: Blackbody D65" -msgstr "Звезден цвят: Цветови стандарт D65" +msgstr "Звезден цвят: Чернотелен D65" #: ../src/celestia/celestiacore.cpp:1124 -#, fuzzy msgid "Star color: Blackbody (Solar Whitepoint)" -msgstr "Звезден цвят: Цветови стандарт D65" +msgstr "Звезден цвят: Чернотелен (Бяла точка от Слънцето)" #: ../src/celestia/celestiacore.cpp:1130 -#, fuzzy msgid "Star color: Blackbody (Vega Whitepoint)" -msgstr "Звезден цвят: Цветови стандарт D65" +msgstr "Звезден цвят: Чернотелен (Бяла точка от Вега)" #: ../src/celestia/celestiacore.cpp:1136 -#, fuzzy msgid "Star color: Classic" -msgstr "Звездни цветове" +msgstr "Звезден цвят: Класически" #. Light travel time in years, if >= 1day #: ../src/celestia/celestiacore.cpp:1169 @@ -508,23 +493,23 @@ msgstr "Изгледът е добавен" #: ../src/celestia/celestiacore.cpp:2242 msgid "Skipping solar system catalog: {}\n" -msgstr "Пропускане на системен каталог: {}\n" +msgstr "Пропускане на системния каталог: {}\n" #: ../src/celestia/celestiacore.cpp:2245 msgid "Loading solar system catalog: {}\n" -msgstr "Зареждане на системен каталог: {}\n" +msgstr "Зареждане на системния каталог: {}\n" #: ../src/celestia/celestiacore.cpp:2288 msgid "Skipping {} catalog: {}\n" -msgstr "Пропускане на {} каталог: {}\n" +msgstr "Пропускане на каталога {}: {}\n" #: ../src/celestia/celestiacore.cpp:2291 msgid "Loading {} catalog: {}\n" -msgstr "Зареждане на {} каталог: {}\n" +msgstr "Зареждане на каталога {}: {}\n" #: ../src/celestia/celestiacore.cpp:2299 msgid "Error reading {} catalog file: {}\n" -msgstr "Грешка при четене на {} каталог: {}\n" +msgstr "Грешка при четене на каталога {}: {}\n" #: ../src/celestia/celestiacore.cpp:2333 msgid "Error reading configuration file." @@ -532,7 +517,7 @@ msgstr "Грешка при четене на конфигурационния #: ../src/celestia/celestiacore.cpp:2347 msgid "Initialization of SPICE library failed." -msgstr "Създаването на библиотеката „SPICE“ се провали." +msgstr "Създаването на библиотеката SPICE се провали." #: ../src/celestia/celestiacore.cpp:2392 msgid "Cannot read star database." @@ -564,11 +549,11 @@ msgstr "Грешка при зареждане на шрифта, текстът #: ../src/celestia/celestiacore.cpp:2739 msgid "Error reading cross index {}\n" -msgstr "Грешка при четене на кръстосаното индексиране {}\n" +msgstr "Грешка при четене на кръстосания индекс {}\n" #: ../src/celestia/celestiacore.cpp:2741 msgid "Loaded cross index {}\n" -msgstr "Кръстосаното индексиране {} е заредено\n" +msgstr "Кръстосаният индекс {} е зареден\n" #: ../src/celestia/celestiacore.cpp:2758 msgid "Error reading star names file\n" @@ -605,12 +590,12 @@ msgstr "Грешка при отваряне на астеризмите {}.\n" #: ../src/celestia/gtk/actions.cpp:90 ../src/celestia/qt/qtappwin.cpp:747 #: ../src/celestia/win32/winmoviecapture.cpp:68 msgid "Lossless" -msgstr "Без загуба" +msgstr "Некомпресирано" #: ../src/celestia/gtk/actions.cpp:91 ../src/celestia/qt/qtappwin.cpp:748 #: ../src/celestia/win32/winmoviecapture.cpp:69 msgid "Lossy (H.264)" -msgstr "Със загуба (H.264)" +msgstr "Компресирано (H.264)" #: ../src/celestia/gtk/actions.cpp:745 ../src/celestia/qt/qtappwin.cpp:1259 #: ../src/celestia/qt/qtappwin.cpp:1676 @@ -621,7 +606,7 @@ msgstr "За „Celestia“" #: ../src/celestia/gtk/actions.cpp:1107 #: ../src/celestia/win32/winfiledlgs.cpp:97 msgid "Please use a name ending in '.jpg' or '.png'." -msgstr "Моля, използвайте име, завършващо с „.jpg“ или „.png“." +msgstr "Моля, използвайте име, завършващо с .jpg или .png." #: ../src/celestia/helper.cpp:106 ../src/celestia/helper.cpp:115 #, c-format @@ -639,14 +624,14 @@ msgid "Renderer: %s\n" msgstr "Възпроизвеждане: %s\n" #: ../src/celestia/helper.cpp:118 -#, fuzzy, c-format +#, c-format msgid "Color component: %s\n" -msgstr "Елементи" +msgstr "Цветен компонент: %s\n" #: ../src/celestia/helper.cpp:121 -#, fuzzy, c-format +#, c-format msgid "Depth component: %s\n" -msgstr "Елементи" +msgstr "Дълбочинен компонент: %s\n" #: ../src/celestia/helper.cpp:124 #, c-format @@ -661,12 +646,12 @@ msgstr "Максимален размер на текстурите: %s\n" #: ../src/celestia/helper.cpp:130 #, c-format msgid "Point size range: %s - %s\n" -msgstr "Диапазон на размера на точките: %s - %s\n" +msgstr "Диапазон на размера на точките: %s – %s\n" #: ../src/celestia/helper.cpp:133 #, c-format msgid "Line width range: %s - %s\n" -msgstr "Диапазон на размера на линиите: %s - %s\n" +msgstr "Диапазон на размера на линиите: %s – %s\n" #: ../src/celestia/helper.cpp:136 #, c-format @@ -751,22 +736,18 @@ msgid "Rotation period: {} {}\n" msgstr "Период на въртене: {} {}\n" #: ../src/celestia/hud.cpp:182 -#, fuzzy msgid "Mass: {} lb\n" -msgstr "Маса: {} лб\n" +msgstr "Маса: {} фунта\n" #: ../src/celestia/hud.cpp:185 -#, fuzzy msgid "Mass: {} kg\n" msgstr "Маса: {} кг\n" #: ../src/celestia/hud.cpp:189 -#, fuzzy msgid "Mass: {} Mj\n" msgstr "Маса: {} Юп\n" #: ../src/celestia/hud.cpp:192 -#, fuzzy msgid "Mass: {} Me\n" msgstr "Маса: {} Зем\n" @@ -875,7 +856,7 @@ msgstr "Радиус: {}\n" #: ../src/celestia/hud.cpp:476 msgid "Planetary companions present\n" -msgstr "Налични са планетарни спътници\n" +msgstr "Присъстват планетарни спътници\n" #: ../src/celestia/hud.cpp:496 #, c-format @@ -893,14 +874,12 @@ msgid "Phase angle: %.1f%s\n" msgstr "Фазов ъгъл: %.1f%s\n" #: ../src/celestia/hud.cpp:585 -#, fuzzy msgid "Density: {} lb/ft³\n" -msgstr "Плътност: %.2f х 1000 лб/фт^3\n" +msgstr "Плътност: {} фунта/фт³\n" #: ../src/celestia/hud.cpp:590 -#, fuzzy msgid "Density: {} kg/m³\n" -msgstr "Плътност: %.2f х 1000 кг/м^3\n" +msgstr "Плътност: {} кг/м³\n" #: ../src/celestia/hud.cpp:596 #, c-format @@ -1003,17 +982,15 @@ msgstr "F11 за Старт и Пауза F12 за Спиране" #. TRANSLATORS: fps == frames per second #: ../src/celestia/qt/qtappwin.cpp:209 -#, fuzzy msgctxt "fps" msgid "Auto" -msgstr "Автоматично" +msgstr "Автоматична" #. TRANSLATORS: fps == frames per second #: ../src/celestia/qt/qtappwin.cpp:216 -#, fuzzy msgctxt "fps" msgid "Custom" -msgstr "Персонализирано" +msgstr "Персонализирана" #: ../src/celestia/qt/qtappwin.cpp:257 msgid "Error getting path for log filename!" @@ -1021,8 +998,8 @@ msgstr "Грешка при получаване на пътя за името #: ../src/celestia/qt/qtappwin.cpp:272 msgid "" -"Celestia is unable to run because the data directory was not found, probably " -"due to improper installation." +"Celestia is unable to run because the data directory was not found, probably" +" due to improper installation." msgstr "" "„Celestia“ не успя да стартира, защото папката с данни липсва, вероятната " "причина е неправилна инсталация." @@ -1060,7 +1037,8 @@ msgstr "Звезди" msgid "Deep Sky Objects" msgstr "Обекти от дълбокото небе" -#: ../src/celestia/qt/qtappwin.cpp:393 ../src/celestia/qt/qteventfinder.cpp:414 +#: ../src/celestia/qt/qtappwin.cpp:393 +#: ../src/celestia/qt/qteventfinder.cpp:414 #: ../src/celestia/qt/qteventfinder.cpp:424 msgid "Event Finder" msgstr "Търсач на събития" @@ -1086,11 +1064,11 @@ msgstr "Цял екран" #: ../src/celestia/qt/qtappwin.cpp:466 msgid "ALT+Enter" -msgstr "" +msgstr "ALT+Enter" #: ../src/celestia/qt/qtappwin.cpp:466 msgid "ALT+Return" -msgstr "" +msgstr "ALT+Return" #: ../src/celestia/qt/qtappwin.cpp:626 msgid "Error opening bookmarks file" @@ -1161,42 +1139,43 @@ msgid "Celestia Scripts (*.celx *.cel)" msgstr "Скриптове на „Celestia“ (*.celx *.cel)" #: ../src/celestia/qt/qtappwin.cpp:974 -#, fuzzy msgid "Celestia Scripts (*.cel)" -msgstr "Скриптове на „Celestia“ (*.celx *.cel)" +msgstr "Скриптове на „Celestia“ (*.cel)" #: ../src/celestia/qt/qtappwin.cpp:1148 msgid "New bookmark" msgstr "Нова отметка" #: ../src/celestia/qt/qtappwin.cpp:1209 -#, fuzzy, qt-format +#, qt-format msgid "" -"

Celestia 1.7.0

Development snapshot, commit %1.

Built for %2 bit CPU
Using %3 %4
Built against Qt library: " -"%5
NAIF kernels are %7
AVIF images are %8
Runtime Qt version: %6

Copyright (C) 2001-2023 by the Celestia Development Team.
Celestia " -"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.

Main site: https://" -"celestiaproject.space/
Forum: https://celestiaproject.space/forum/
GitHub project: https://github.com/" -"CelestiaProject/Celestia

" +"

Celestia 1.7.0

Development snapshot, commit " +"%1.

Built for %2 bit CPU
Using %3 %4
Built against Qt " +"library: %5
NAIF kernels are %7
AVIF images are %8
Runtime Qt " +"version: %6

Copyright (C) 2001-2023 by the Celestia Development " +"Team.
Celestia 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.

Main site: https://celestiaproject.space/
Forum:" +" https://celestiaproject.space/forum/
GitHub" +" project: https://github.com/CelestiaProject/Celestia

" msgstr "" -"

„Celestia“ 1.7

В процес на разработка, компилация %1." -"

За %2 битови процесори
Използва %3 %4
Създадена е с Qt: " -"%5
Ядрата NAIF са %7
Изображенията AVIF са %8

Версия на Qt: %6

Авторско право (C) 2001-2021, Екипа на „Celestia“.
„Celestia“ е " -"безплатен софтуер. Може да се разпространява и/или променя под условията на " -"„GNU General Public License“, който е публикуван от „Фондацията за свободен " -"софтуер“, версия 2 или всяка по-нова версия на Лиценза (по Ваша преценка).

Сайт: https://" -"celestiaproject.space/
Форум: https://celestiaproject.space/forum/
„GitHub“: https://github.com/" -"CelestiaProject/Celestia

" +"

„Celestia“ 1.7.0

В процес на разработка, компилация " +"%1.

За %2 битови процесори
Използва %3 %4
Създадена с Qt:" +" %5
Ядрата NAIF са %7
Изображенията AVIF са %8
Версия на Qt: " +"%6

Авторско право (C) 2001-2023, Екипът на „Celestia“.
„Celestia“ е" +" безплатен софтуер. Може да се разпространява и/или променя под условията на" +" „GNU General Public License“, който е публикуван от „Фондацията за свободен" +" софтуер“, версия 2 или всяка по-нова версия на Лиценза (по Ваша " +"преценка).

Сайт: https://celestiaproject.space/
Форум:" +" https://celestiaproject.space/forum/
„GitHub“:" +" https://github.com/CelestiaProject/Celestia

" #: ../src/celestia/qt/qtappwin.cpp:1245 msgid "Unknown compiler" @@ -1478,18 +1457,16 @@ msgid "&Help" msgstr "&Помощ" #: ../src/celestia/qt/qtappwin.cpp:1664 -#, fuzzy msgid "Celestia Guide" -msgstr "„Celestia“" +msgstr "Ръководство на „Celestia“" #: ../src/celestia/qt/qtappwin.cpp:1667 -#, fuzzy msgid "Celestia Wiki" -msgstr "„Celestia“" +msgstr "Уикипедия на „Celestia“" #: ../src/celestia/qt/qtappwin.cpp:1672 msgid "OpenGL Info" -msgstr "Информация за „OpenGL“" +msgstr "Информация за OpenGL" #: ../src/celestia/qt/qtappwin.cpp:1693 msgid "Add Bookmark..." @@ -1513,7 +1490,7 @@ msgid "" "Loading data files: %1\n" "\n" msgstr "" -"Зареждане на файлове с данни: %1\n" +"Зареждане на файловете с данни: %1\n" "\n" #: ../src/celestia/qt/qtappwin.cpp:1779 @@ -1547,7 +1524,7 @@ msgstr "Добави отметките в тази папка за да се п #: ../src/celestia/qt/qtbookmark.cpp:644 msgid "Error reading bookmarks file" -msgstr "Грешка при четене на файла с отметки" +msgstr "Грешка при четене на файла с отметките" #. Create a subtree item called "Bookmarks" #: ../src/celestia/qt/qtbookmark.cpp:761 @@ -1569,7 +1546,8 @@ msgid "System time at activation" msgstr "Системно време при активиране" #. i18n: file: ../src/celestia/qt/newbookmarkfolder.ui:13 -#. i18n: ectx: property (windowTitle), widget (QDialog, newBookmarkFolderDialog) +#. i18n: ectx: property (windowTitle), widget (QDialog, +#. newBookmarkFolderDialog) #. i18n: file: ../src/celestia/qt/organizebookmarks.ui:24 #. i18n: ectx: property (text), widget (QPushButton, newFolderButton) #: ../src/celestia/qt/qtbookmark.cpp:897 ../src/celestia/qt/rc.cpp:39 @@ -1680,8 +1658,9 @@ msgstr "Орбити" #: ../src/celestia/qt/qtcelestiaactions.cpp:95 #: ../src/celestia/qt/qtcelestiaactions.cpp:122 #: ../src/celestia/qt/qtselectionpopup.cpp:402 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:101 ../src/celestia/qt/rc.cpp:75 -#: ../src/celestia/qt/rc.cpp:157 ../src/celestia/qt/rc.cpp:224 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:101 +#: ../src/celestia/qt/rc.cpp:75 ../src/celestia/qt/rc.cpp:157 +#: ../src/celestia/qt/rc.cpp:224 #: ../src/celestia/win32/res/resource_strings.cpp:216 #: ../src/celestia/win32/wincontextmenu.cpp:160 #: ../src/celestia/win32/wincontextmenu.cpp:319 @@ -1703,8 +1682,9 @@ msgstr "Планети джуджета" #: ../src/celestia/qt/qtcelestiaactions.cpp:97 #: ../src/celestia/qt/qtcelestiaactions.cpp:124 #: ../src/celestia/qt/qtselectionpopup.cpp:408 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:103 ../src/celestia/qt/rc.cpp:81 -#: ../src/celestia/qt/rc.cpp:163 ../src/celestia/qt/rc.cpp:230 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:103 +#: ../src/celestia/qt/rc.cpp:81 ../src/celestia/qt/rc.cpp:163 +#: ../src/celestia/qt/rc.cpp:230 #: ../src/celestia/win32/res/resource_strings.cpp:218 #: ../src/celestia/win32/wincontextmenu.cpp:156 msgid "Moons" @@ -1725,8 +1705,9 @@ msgstr "Астероидни спътници" #: ../src/celestia/qt/qtcelestiaactions.cpp:99 #: ../src/celestia/qt/qtcelestiaactions.cpp:126 #: ../src/celestia/qt/qtselectionpopup.cpp:414 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:771 ../src/celestia/qt/rc.cpp:87 -#: ../src/celestia/qt/rc.cpp:169 ../src/celestia/qt/rc.cpp:236 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:771 +#: ../src/celestia/qt/rc.cpp:87 ../src/celestia/qt/rc.cpp:169 +#: ../src/celestia/qt/rc.cpp:236 #: ../src/celestia/win32/res/resource_strings.cpp:220 #: ../src/celestia/win32/wincontextmenu.cpp:150 msgid "Asteroids" @@ -1741,8 +1722,9 @@ msgstr "Астероиди" #: ../src/celestia/qt/qtcelestiaactions.cpp:100 #: ../src/celestia/qt/qtcelestiaactions.cpp:127 #: ../src/celestia/qt/qtselectionpopup.cpp:417 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:779 ../src/celestia/qt/rc.cpp:90 -#: ../src/celestia/qt/rc.cpp:172 ../src/celestia/qt/rc.cpp:239 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:779 +#: ../src/celestia/qt/rc.cpp:90 ../src/celestia/qt/rc.cpp:172 +#: ../src/celestia/qt/rc.cpp:239 #: ../src/celestia/win32/res/resource_strings.cpp:221 #: ../src/celestia/win32/wincontextmenu.cpp:152 msgid "Comets" @@ -1762,8 +1744,9 @@ msgstr "Комети" #: ../src/celestia/qt/qtcelestiaactions.cpp:128 #: ../src/celestia/qt/qtselectionpopup.cpp:420 #: ../src/celestia/qt/qtsolarsystembrowser.cpp:105 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:775 ../src/celestia/qt/rc.cpp:94 -#: ../src/celestia/qt/rc.cpp:176 ../src/celestia/qt/rc.cpp:243 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:775 +#: ../src/celestia/qt/rc.cpp:94 ../src/celestia/qt/rc.cpp:176 +#: ../src/celestia/qt/rc.cpp:243 #: ../src/celestia/win32/res/resource_strings.cpp:222 #: ../src/celestia/win32/wincontextmenu.cpp:166 msgctxt "plural" @@ -2156,53 +2139,52 @@ msgstr "%1 намерени обекта" #: ../src/celestia/qt/qtcommandline.cpp:16 msgid "Set the data directory." -msgstr "" +msgstr "Задай папката с данните." #: ../src/celestia/qt/qtcommandline.cpp:16 msgid "datadir" -msgstr "" +msgstr "папка с данни" #: ../src/celestia/qt/qtcommandline.cpp:17 -#, fuzzy msgid "Set the configuraton file." -msgstr "{}: Неточен конфигурационен файл.\n" +msgstr "Задай конфигурационният файл." #: ../src/celestia/qt/qtcommandline.cpp:17 msgid "conf" -msgstr "" +msgstr "конфигурационен файл" #: ../src/celestia/qt/qtcommandline.cpp:18 msgid "Add an extras directory. This option may be specified multiple times." msgstr "" +"Добави папка с допълнения. Тази опция може да бъде зададена няколко пъти." #: ../src/celestia/qt/qtcommandline.cpp:18 msgid "extrasdir" -msgstr "" +msgstr "папка с допълнения" #: ../src/celestia/qt/qtcommandline.cpp:19 msgid "Start in fullscreen mode." -msgstr "" +msgstr "Започни в режим на цял екран." #: ../src/celestia/qt/qtcommandline.cpp:20 msgid "Skip the splash screen." -msgstr "" +msgstr "Пропусни началния екран." #: ../src/celestia/qt/qtcommandline.cpp:21 msgid "Set the start cel:// URL or startup script path." -msgstr "" +msgstr "Задай пътя към началната връзка или скрипт." #: ../src/celestia/qt/qtcommandline.cpp:21 -#, fuzzy msgid "url" -msgstr "Юли" +msgstr "връзка" #: ../src/celestia/qt/qtcommandline.cpp:22 msgid "Set the path to the log file." -msgstr "" +msgstr "Задай пътя към дневника." #: ../src/celestia/qt/qtcommandline.cpp:22 msgid "logpath" -msgstr "" +msgstr "път към дневника" #: ../src/celestia/qt/qtdeepskybrowser.cpp:523 msgid "Mark DSOs selected in list view" @@ -2315,13 +2297,12 @@ msgid "Behind %1" msgstr "Зад %1" #: ../src/celestia/qt/qtglwidget.cpp:105 -#, fuzzy msgid "Celestia was unable to initialize OpenGLES 2.0." -msgstr "„Celestia“ не успя да стартира „OpenGL“ 2.1." +msgstr "„Celestia“ не успя да стартира OpenGLES 2.0." #: ../src/celestia/qt/qtglwidget.cpp:112 msgid "Celestia was unable to initialize OpenGL 2.1." -msgstr "„Celestia“ не успя да стартира „OpenGL“ 2.1." +msgstr "„Celestia“ не успя да стартира OpenGL 2.1." #: ../src/celestia/qt/qtinfopanel.cpp:155 msgid "Error: no object selected!\n" @@ -2460,9 +2441,9 @@ msgid "Period (calculated): %L1 %2" msgstr "Период (изчислен): %L1 %2" #: ../src/celestia/qt/qtinfopanel.cpp:338 -#, fuzzy, qt-format +#, qt-format msgid "Mean motion (calculated): %L1%2/day" -msgstr "Период (изчислен): %L1 %2" +msgstr "Средно движение (изчислено): %L1%2/на ден" #: ../src/celestia/qt/qtinfopanel.cpp:362 #: ../src/celestia/qt/qtinfopanel.cpp:385 @@ -2490,22 +2471,22 @@ msgstr "B: %L1%2 %L3' %L4\"" #: ../src/celestia/qt/qtpreferencesdialog.cpp:210 msgid "OpenGL 2.1" -msgstr "„OpenGL“ 2.1" +msgstr "OpenGL 2.1" #: ../src/celestia/qt/qtpreferencesdialog.cpp:254 #: ../src/celestia/win32/res/resource_strings.cpp:43 msgid "Blackbody D65" -msgstr "Цветови стандарт D65" +msgstr "Чернотелен D65" #: ../src/celestia/qt/qtpreferencesdialog.cpp:255 #: ../src/celestia/win32/res/resource_strings.cpp:44 msgid "Blackbody (Solar Whitepoint)" -msgstr "" +msgstr "Чернотелен (Бяла точка от Слънцето)" #: ../src/celestia/qt/qtpreferencesdialog.cpp:256 #: ../src/celestia/win32/res/resource_strings.cpp:45 msgid "Blackbody (Vega Whitepoint)" -msgstr "" +msgstr "Чернотелен (Бяла точка от Вега)" #: ../src/celestia/qt/qtpreferencesdialog.cpp:257 #: ../src/celestia/win32/res/resource_strings.cpp:46 @@ -2522,7 +2503,7 @@ msgstr "Име на часовата зона" #: ../src/celestia/qt/qtpreferencesdialog.cpp:266 msgid "UTC offset" -msgstr "Отклонение по „UTC“" +msgstr "Отклонение по UTC" #: ../src/celestia/qt/qtselectionpopup.cpp:98 #, qt-format @@ -2688,9 +2669,9 @@ msgstr "Планети джуджета" #. i18n: file: ../src/celestia/qt/preferences.ui:527 #. i18n: ectx: property (text), widget (QCheckBox, minorMoonLabelsCheck) #: ../src/celestia/qt/qtselectionpopup.cpp:411 -#: ../src/celestia/qt/qtsolarsystembrowser.cpp:111 ../src/celestia/qt/rc.cpp:84 -#: ../src/celestia/qt/rc.cpp:166 ../src/celestia/qt/rc.cpp:233 -#: ../src/celestia/win32/wincontextmenu.cpp:158 +#: ../src/celestia/qt/qtsolarsystembrowser.cpp:111 +#: ../src/celestia/qt/rc.cpp:84 ../src/celestia/qt/rc.cpp:166 +#: ../src/celestia/qt/rc.cpp:233 ../src/celestia/win32/wincontextmenu.cpp:158 msgid "Minor moons" msgstr "Астероидни спътници" @@ -2879,7 +2860,7 @@ msgstr "Задай към текущото време" #: ../src/celestia/qt/qttourguide.cpp:61 msgid "No guide destinations were found." -msgstr "" +msgstr "Няма намерени дестинации на екскурзовода." #. i18n: file: ../src/celestia/qt/addbookmark.ui:16 #. i18n: ectx: property (windowTitle), widget (QDialog, addBookmarkDialog) @@ -2957,7 +2938,8 @@ msgid "Description:" msgstr "Описание:" #. i18n: file: ../src/celestia/qt/organizebookmarks.ui:13 -#. i18n: ectx: property (windowTitle), widget (QDialog, organizeBookmarksDialog) +#. i18n: ectx: property (windowTitle), widget (QDialog, +#. organizeBookmarksDialog) #: ../src/celestia/qt/rc.cpp:51 #: ../src/celestia/win32/res/resource_strings.cpp:156 msgid "Organize Bookmarks" @@ -3224,23 +3206,20 @@ msgstr "Резолюция на текстурите" #. i18n: file: ../src/celestia/qt/preferences.ui:865 #. i18n: ectx: property (title), widget (QGroupBox, ambientLightGroupBox) #: ../src/celestia/qt/rc.cpp:318 -#, fuzzy msgid "Lighting" -msgstr "Увеличение на светлината" +msgstr "Светлина" #. i18n: file: ../src/celestia/qt/preferences.ui:871 #. i18n: ectx: property (text), widget (QLabel, label_4) #: ../src/celestia/qt/rc.cpp:321 -#, fuzzy msgid "Ambient light:" -msgstr "Фонова светлина" +msgstr "Фонова светлина:" #. i18n: file: ../src/celestia/qt/preferences.ui:932 #. i18n: ectx: property (text), widget (QLabel, label_5) #: ../src/celestia/qt/rc.cpp:324 -#, fuzzy msgid "Tinted illumination saturation:" -msgstr "Тонирано осветление" +msgstr "Тонирана наситеност на осветяването:" #. i18n: file: ../src/celestia/qt/preferences.ui:991 #. i18n: ectx: property (title), widget (QGroupBox, renderPathGroupBox) @@ -3307,12 +3286,11 @@ msgstr "Отиди до" #: ../src/celestia/qt/xbel.cpp:78 msgid "Not an XBEL version 1.0 file." -msgstr "Не е файл с версия 1.0 на „XBEL“." +msgstr "Не е файл с версия 1.0 на XBEL." #: ../src/celestia/textinput.cpp:191 -#, fuzzy msgid "Target name: {}" -msgstr "Име на целта: %s" +msgstr "Име на целта: {}" #: ../src/celestia/url.cpp:349 msgid "Incorrect hex value \"{}\"\n" @@ -3348,7 +3326,7 @@ msgstr "Неподдържана версия на връзката: {}\n" #: ../src/celestia/url.cpp:552 msgid "URL parameter must look like key=value\n" -msgstr "Параметърът на връзката трябва да изглежда така: key=value\n" +msgstr "Параметърът на връзката трябва да изглежда така: ключ=стойност\n" #: ../src/celestia/win32/res/resource_strings.cpp:4 msgid "Placeholder" @@ -3560,7 +3538,7 @@ msgstr "Контроли" #: ../src/celestia/win32/res/resource_strings.cpp:69 msgid "&OpenGL Info" -msgstr "Информация за „OpenGL“" +msgstr "Информация за OpenGL" #: ../src/celestia/win32/res/resource_strings.cpp:70 msgid "&License" @@ -3599,7 +3577,7 @@ msgstr "1.7.0" #: ../src/celestia/win32/res/resource_strings.cpp:76 msgid "Copyright (C) 2001-2021, Celestia Development Team" -msgstr "Авторско право (С) 2001-2021, Екипа на „Celestia“" +msgstr "Авторско право (С) 2001-2021, Екипът на „Celestia“" #: ../src/celestia/win32/res/resource_strings.cpp:77 msgid "Celestia is free software and comes with absolutely no warranty." @@ -3740,7 +3718,7 @@ msgstr "Име на обект" #: ../src/celestia/win32/res/resource_strings.cpp:121 msgid "OpenGL Driver Info" -msgstr "Информация за драйвъра на „OpenGL“" +msgstr "Информация за драйвъра на OpenGL" #: ../src/celestia/win32/res/resource_strings.cpp:123 msgid "Go to Object" @@ -3970,7 +3948,7 @@ msgstr "Сеп" #: ../src/celestia/win32/winbookmarks.cpp:1484 msgid "(empty)" -msgstr "" +msgstr "(празно)" #: ../src/celestia/win32/wincontextmenu.cpp:154 msgid "Invisibles" @@ -4012,7 +3990,7 @@ msgstr "Сателити" #: ../src/celestia/win32/wincontextmenu.cpp:317 msgid "Orbiting Bodies" -msgstr "Орбитиращи тела" +msgstr "Орбитални тела" #. Add windowed mode as the first item on the menu #: ../src/celestia/win32/windisplaymodedlg.cpp:46 @@ -4021,7 +3999,7 @@ msgstr "В прозорец" #: ../src/celestia/win32/wineclipses.cpp:72 msgid "Body" -msgstr "" +msgstr "Тяло" #: ../src/celestia/win32/wineclipses.cpp:74 msgid "Date" @@ -4033,11 +4011,11 @@ msgstr "Старт" #: ../src/celestia/win32/winfiledlgs.cpp:47 msgid "JPEG - JFIF Compliant (*.jpg)" -msgstr "" +msgstr "Съвместимо с JPEG – JFIF (*.jpg)" #: ../src/celestia/win32/winfiledlgs.cpp:49 msgid "Portable Network Graphics (*.png)" -msgstr "" +msgstr "Преносими мрежови графики (*.png)" #: ../src/celestia/win32/winfiledlgs.cpp:64 msgid "Save As - Specify File to Capture Image" @@ -4058,16 +4036,18 @@ msgid "Could not save image file." msgstr "Изображението не може да бъде запазено." #: ../src/celestia/win32/winfiledlgs.cpp:122 -#, fuzzy msgid "Celestia Script (*.celx, *.cel)" -msgstr "Скриптове на „Celestia“ (*.celx *.cel)" +msgstr "Скрипт на „Celestia“ (*.celx, *.cel)" -#. Gettext complains about using \r in translated messages, so add it in afterwards +#. Gettext complains about using \r in translated messages, so add it in +#. afterwards #: ../src/celestia/win32/winhelpdlgs.cpp:157 msgid "" "License file missing!\n" "See {}" msgstr "" +"Лицензът липсва!\n" +"Вижте {}" #: ../src/celestia/win32/winmain.cpp:143 msgid "Unable to switch to full screen mode; running in window mode" @@ -4083,7 +4063,7 @@ msgstr "Фатална грешка" #: ../src/celestia/win32/winmain.cpp:407 msgid "Directory expected after --dir" -msgstr "Очаква се име на папката след параметъра „--dir“" +msgstr "Очаква се име на папката след параметъра --dir" #: ../src/celestia/win32/winmain.cpp:408 ../src/celestia/win32/winmain.cpp:420 #: ../src/celestia/win32/winmain.cpp:433 ../src/celestia/win32/winmain.cpp:445 @@ -4093,29 +4073,27 @@ msgstr "Грешка в командния ред на „Celestia“" #: ../src/celestia/win32/winmain.cpp:419 msgid "Configuration file name expected after --conf" -msgstr "Очаква се име на конфигурационния файл след параметъра „--conf“" +msgstr "Очаква се име на конфигурационния файл след параметъра --conf" #: ../src/celestia/win32/winmain.cpp:432 msgid "Directory expected after --extrasdir" -msgstr "Очаква се име на папката след параметъра „--extrasdir“" +msgstr "Очаква се име на папката след параметъра --extrasdir" #: ../src/celestia/win32/winmain.cpp:444 msgid "URL expected after --url" -msgstr "Очаква се връзка след параметъра „--url“" +msgstr "Очаква се връзка след параметъра --url" #: ../src/celestia/win32/winmain.cpp:458 -#, fuzzy msgid "Invalid command line option '{}'" -msgstr "Невалидна опция на командния ред „%s“" +msgstr "Невалидна опция на командния ред „{}“" #: ../src/celestia/win32/winmain.cpp:485 -#, fuzzy msgid "Loading: {}" -msgstr "Зареждане: " +msgstr "Зареждане: {}" #: ../src/celestia/win32/winmain.cpp:559 msgid "Loading data files..." -msgstr "Зареждане на файлове с данни..." +msgstr "Зареждане на файловете с данни..." #: ../src/celestia/win32/winmain.cpp:637 ../src/celutil/fsutils.cpp:41 msgid "LANGUAGE" @@ -4123,14 +4101,13 @@ msgstr "bg" #: ../src/celestia/win32/winmain.cpp:655 msgid "Could not load localized resources: {}\n" -msgstr "" +msgstr "Локализираните ресурси не може да бъдат заредени: {}\n" #: ../src/celestia/win32/winmain.cpp:660 msgid "Loaded localized resource: {}\n" -msgstr "" +msgstr "Локализираните ресурси са заредени: {}\n" #: ../src/celestia/win32/winmain.cpp:698 -#, fuzzy msgid "Confugration file missing!" msgstr "Конфигурационният файл липсва!" @@ -4151,40 +4128,38 @@ msgid "Failed to create the application window." msgstr "Неуспешно създаване на прозореца на приложението." #: ../src/celestia/win32/winmain.cpp:785 -#, fuzzy msgid "Error locking drop target\n" -msgstr "Грешка при отваряне на звездния каталог {}\n" +msgstr "Грешка при заключване на целта\n" #: ../src/celestia/win32/winmain.cpp:794 -#, fuzzy msgid "Failed to register drop target as OLE object.\n" -msgstr "Неуспешно регистриране на прозоречния клас." +msgstr "Неуспешно регистриране на целта като OLE обект.\n" #: ../src/celestia/win32/winmainwindow.cpp:260 msgid "Error getting joystick caps.\n" -msgstr "" +msgstr "Грешка при получаване на обратна връзка от джойстика.\n" #: ../src/celestia/win32/winmainwindow.cpp:264 msgid "Using joystick: {}\n" -msgstr "" +msgstr "Използван джойстик: {}\n" #: ../src/celestia/win32/winmainwindow.cpp:725 msgid "Loading URL" -msgstr "Зареждане на връзка" +msgstr "Зареждане на връзката" #: ../src/celestia/win32/winmainwindow.cpp:1135 msgid "Could not get appropriate pixel format for OpenGL rendering." msgstr "" -"Не може да бъде избран подходящ формат на пикселите за възпроизвеждане с " -"„OpenGL“." +"Подходящият формат на пикселите за възпроизвеждане с OpenGL не може да бъде " +"избран." #: ../src/celestia/win32/winmainwindow.cpp:1153 msgid "Your system doesn't support OpenGL 2.1!" -msgstr "Вашата система не поддържа „OpenGL“ 2.1!" +msgstr "Вашата система не поддържа OpenGL 2.1!" #: ../src/celestia/win32/winmainwindow.cpp:1170 msgid "Releasing device context failed." -msgstr "Неуспешно извличане на контекста на устройството." +msgstr "Извличането на контекста на устройството се провали." #: ../src/celestia/win32/winmainwindow.cpp:1568 msgid "Failed to register the window class." @@ -4195,9 +4170,8 @@ msgid "Stop current movie capture before starting another one." msgstr "Спри текущото прихващане на видео, преди започване на следващото." #: ../src/celestia/win32/winmoviecapture.cpp:240 -#, fuzzy msgid "Matroska (*.mkv)" -msgstr "Видео формат „Матрьошка“ (*.mkv)" +msgstr "Формат „Матрьошка“ (*.mkv)" #: ../src/celestia/win32/winmoviecapture.cpp:258 msgid "Save As - Specify Output File for Capture Movie" @@ -4214,23 +4188,20 @@ msgstr "Видеото не може да бъде прихванато." #: ../src/celestia/win32/winpreferences.cpp:202 #: ../src/celestia/win32/winpreferences.cpp:261 -#, fuzzy msgid "Error opening registry key: {}\n" -msgstr "Грешка при отваряне на скрипта {}" +msgstr "Грешка при отваряне на ключа от регистъра: {}\n" #: ../src/celestia/win32/winpreferences.cpp:253 -#, fuzzy msgid "Saving preferences...\n" -msgstr "Предпочитания..." +msgstr "Запазване на предпочитанията...\n" #: ../src/celestia/win32/winpreferences.cpp:265 msgid "Opened registry key\n" -msgstr "" +msgstr "Ключът от регистъра е отворен\n" #: ../src/celestia/win32/winsplash.cpp:122 -#, fuzzy msgid "Version: {}" -msgstr "Версия: " +msgstr "Версия: {}" #: ../src/celestia/win32/wintime.cpp:99 msgid "Time Zone Name" @@ -4238,20 +4209,19 @@ msgstr "Име на часовата зона" #: ../src/celestia/win32/wintime.cpp:100 msgid "UTC Offset" -msgstr "Отклонение по „UTC“" +msgstr "Отклонение по UTC" #: ../src/celimage/image.cpp:385 msgid "Loading image from file {}\n" -msgstr "Зареждане на изображение от файл {}\n" +msgstr "Зареждане на изображение от файла {}\n" #: ../src/celimage/image.cpp:409 msgid "{}: unrecognized or unsupported image file type.\n" -msgstr "" +msgstr "{}: неразпознат или неподдържан формат на изображението.\n" #: ../src/celimage/png.cpp:27 -#, fuzzy msgid "Error reading PNG data" -msgstr "Грешка при четене на „PNG“ изображението {}\n" +msgstr "Грешка при четене на PNG данните" #: ../src/celimage/png.cpp:49 msgid "Can't open screen capture file '{}'\n" @@ -4259,7 +4229,7 @@ msgstr "Прихванатото изображение „{}“ не може #: ../src/celimage/png.cpp:105 msgid "Error writing PNG file '{}'\n" -msgstr "Грешка при записване на „PNG“ изображението „{}“\n" +msgstr "Грешка при записване на PNG изображението „{}“\n" #: ../src/celimage/png.cpp:153 msgid "Error opening image file {}.\n" @@ -4267,11 +4237,11 @@ msgstr "Грешка при отваряне на изображение {}.\n" #: ../src/celimage/png.cpp:161 msgid "Error: {} is not a PNG file.\n" -msgstr "Грешка: {} не е „PNG“ файл.\n" +msgstr "Грешка: {} не е PNG файл.\n" #: ../src/celimage/png.cpp:187 msgid "Error reading PNG image file {}\n" -msgstr "Грешка при четене на „PNG“ изображението {}\n" +msgstr "Грешка при четене на PNG изображението {}\n" #: ../src/celscript/legacy/legacyscript.cpp:101 msgid "Error opening script file." @@ -4280,16 +4250,16 @@ msgstr "Грешка при отваряне на скрипта." #: ../src/celscript/legacy/legacyscript.cpp:110 #: ../src/celscript/lua/luascript.cpp:99 msgid "Unknown error loading script" -msgstr "Неизвестна грешка при зареждането на скрипта" +msgstr "Неизвестна грешка при зареждане на скрипта" #. TRANSLATORS: Y is first letter of Yes #: ../src/celscript/lua/celx.cpp:434 msgid "Y" -msgstr "" +msgstr "Д" #: ../src/celscript/lua/celx.cpp:735 msgid "In line {}: {}" -msgstr "Съответства {}: {}" +msgstr "На линия {}: {}" #: ../src/celscript/lua/celx.cpp:780 msgid "" @@ -4309,7 +4279,7 @@ msgstr "" "Това може да доведе до потенциален риск за сигурността.\n" "Сигурни ли сте, че искате да продължите?\n" "\n" -"„y“ = да, „ESC“ = спиране на скрипта, всички останали клавиши = не" +"y = да, ESC = спиране на скрипта, всички останали клавиши = не" #: ../src/celscript/lua/celx.cpp:791 msgid "" @@ -4334,7 +4304,7 @@ msgstr "Грешка при отваряне на скрипта {}" #: ../src/celscript/lua/luascript.cpp:107 #: ../src/celscript/lua/luascript.cpp:242 msgid "Script coroutine initialization failed" -msgstr "Корутинното стартиране на скрипта се провали" +msgstr "Съпрограмното стартиране на скрипта се провали" #: ../src/celscript/lua/luascript.cpp:214 msgid "Error opening LuaHook {}" @@ -4342,16 +4312,15 @@ msgstr "Грешка при отваряне на куката на „Lua“ {} #: ../src/celscript/lua/luascript.cpp:231 msgid "Unknown error loading hook script" -msgstr "Неизвестна грешка при зареждането на скрипта кука" +msgstr "Неизвестна грешка при зареждане на скрипта кука" #: ../src/celutil/tzutil.cpp:51 msgid "Unknown value returned by GetTimeZoneInformation()\n" msgstr "„GetTimeZoneInformation()“ отчита неизвестна стойност\n" #: ../src/tools/xyzv2bin/bin2xyzv.cpp:27 -#, fuzzy msgid "Error opening {} or {}.\n" -msgstr "Грешка при отваряне на {} или .\n" +msgstr "Грешка при отваряне на {} или {}.\n" #: ../src/tools/xyzv2bin/bin2xyzv.cpp:49 msgid "Unsupported byte order {}, expected {}.\n" @@ -4359,74 +4328,4 @@ msgstr "Неподдържан байтов ред {}, очакван {}.\n" #: ../src/tools/xyzv2bin/bin2xyzv.cpp:58 msgid "Unsupported digits number {}, expected {}.\n" -msgstr "Неподдържано число {}, очаквано {}.\n" - -#~ msgid "https://celestiaproject.space/" -#~ msgstr "https://celestiaproject.space/" - -#~ msgid "Satellite" -#~ msgstr "Сателит" - -#~ msgid "" -#~ "License file missing!\n" -#~ "See http://www.gnu.org/copyleft/gpl.html" -#~ msgstr "" -#~ "Лицензът липсва!\n" -#~ "Вижте http://www.gnu.org/copyleft/gpl.html" - -#, c-format -#~ msgid "%d x %d" -#~ msgstr "%d x %d" - -#~ msgid "Specified file extension is not recognized." -#~ msgstr "Зададеното разширение на файла не е разпознато." - -#~ msgid "Error opening {}.\n" -#~ msgstr "Грешка при отваряне на {}.\n" - -#~ msgid "GL error: " -#~ msgstr "Грешка при „OpenGL“: " - -#, c-format -#~ msgid "" -#~ "FPS: %.1f, vis. stars stats: [ %zu : %zu : %zu ], vis. DSOs stats: " -#~ "[ %zu : %zu : %zu ]\n" -#~ msgstr "" -#~ "ЧКС: %.1f, стат. на видимите звезди: [ %zu : %zu : %zu ], стат. на " -#~ "видимите ОДК: [ %zu : %zu : %zu ]\n" - -#~ msgid "000; " -#~ msgstr "000; " - -#~ msgid "Error opening config file '{}'.\n" -#~ msgstr "Грешка при отваряне на конфигурационния файл „{}“.\n" - -#~ msgid "{}:{} 'Configuration' expected.\n" -#~ msgstr "{}:{} очаква се „Configuration“.\n" - -#~ msgid "Star color: Enhanced" -#~ msgstr "Звезден цвят: Засилен" - -#~ msgid "Celestia was unable to initialize OpenGL 2.1.\n" -#~ msgstr "„Celestia“ не успя да стартира „OpenGL“ 2.1.\n" - -#~ msgid "Shift+F11" -#~ msgstr "Shift+F11" - -#~ msgid "Celestia Manual" -#~ msgstr "Ръководство за „Celestia“" - -#~ msgid "A filename expected after --log/-l" -#~ msgstr "Очаква се име на файла след параметъра „--log/-l“" - -#~ msgid "S&ynch Orbit" -#~ msgstr "Синхронизирай с орбитата" - -#~ msgid "Set time" -#~ msgstr "Задай времето" - -#~ msgid "&Disabled" -#~ msgstr "Изключен" - -#~ msgid "&Enabled" -#~ msgstr "Включен" +msgstr "Неподдържан брой числа {}, очакван {}.\n" diff --git a/src/celcompat/charconv_impl.cpp b/src/celcompat/charconv_impl.cpp index 215d2fd753..1dc197645a 100644 --- a/src/celcompat/charconv_impl.cpp +++ b/src/celcompat/charconv_impl.cpp @@ -18,6 +18,8 @@ #include +#include + #include "charconv_impl.h" namespace celestia::compat @@ -30,6 +32,7 @@ constexpr std::size_t inf_length = 3; constexpr std::size_t infinity_length = 8; constexpr std::size_t nan_length = 3; constexpr std::size_t hex_prefix_length = 2; +locale_t numberParsingLocale = nullptr; enum class State { @@ -167,19 +170,19 @@ write_buffer(const char* first, const char* last, chars_format fmt, char* buffer inline void parse_value(const char* start, char** end, float& value) { - value = std::strtof(start, end); + value = strtof_l(start, end, numberParsingLocale); } inline void parse_value(const char* start, char** end, double& value) { - value = std::strtod(start, end); + value = strtod_l(start, end, numberParsingLocale); } inline void parse_value(const char* start, char** end, long double& value) { - value = std::strtold(start, end); + value = strtold_l(start, end, numberParsingLocale); } template @@ -191,8 +194,9 @@ from_chars_impl(const char* first, const char* last, T& value, chars_format fmt) from_chars_result result = write_buffer(first, last, fmt, buffer, hex_prefix); if (result.ec != std::errc{}) { return result; } - const char* savedLocale = std::setlocale(LC_NUMERIC, nullptr); - std::setlocale(LC_NUMERIC, "C"); + if (numberParsingLocale == nullptr) + numberParsingLocale = newlocale(LC_NUMERIC_MASK, "C", nullptr); + errno = 0; char* end; T parsed; @@ -213,7 +217,6 @@ from_chars_impl(const char* first, const char* last, T& value, chars_format fmt) result = { first + (end - buffer), std::errc{} }; } - std::setlocale(LC_NUMERIC, savedLocale); return result; } diff --git a/src/celengine/framebuffer.h b/src/celengine/framebuffer.h index 802745940f..52f70bfabe 100644 --- a/src/celengine/framebuffer.h +++ b/src/celengine/framebuffer.h @@ -28,7 +28,6 @@ class FramebufferObject FramebufferObject& operator=(FramebufferObject&&) noexcept; ~FramebufferObject(); - static inline bool isSupported(); bool isValid() const; GLuint width() const { @@ -60,12 +59,3 @@ class FramebufferObject GLuint m_fboId; GLenum m_status; }; - -bool FramebufferObject::isSupported() -{ -#ifdef GL_ES - return true; -#else - return celestia::gl::ARB_framebuffer_object; -#endif -} diff --git a/src/celengine/glsupport.cpp b/src/celengine/glsupport.cpp index 17a9ca6ee4..f4d7fb8168 100644 --- a/src/celengine/glsupport.cpp +++ b/src/celengine/glsupport.cpp @@ -1,6 +1,8 @@ #include "glsupport.h" #include #include +#include +#include namespace celestia::gl { @@ -81,7 +83,11 @@ bool init(util::array_view ignore) noexcept OES_geometry_shader = check_extension(ignore, "GL_OES_geometry_shader") || check_extension(ignore, "GL_EXT_geometry_shader"); #else ARB_vertex_array_object = check_extension(ignore, "GL_ARB_vertex_array_object"); - ARB_framebuffer_object = check_extension(ignore, "GL_ARB_framebuffer_object") || check_extension(ignore, "GL_EXT_framebuffer_object"); + if (!has_extension("GL_ARB_framebuffer_object")) + { + fmt::print(_("Mandatory extension GL_ARB_framebuffer_object is missing!\n")); + return false; + } #endif ARB_shader_texture_lod = check_extension(ignore, "GL_ARB_shader_texture_lod"); EXT_texture_compression_s3tc = check_extension(ignore, "GL_EXT_texture_compression_s3tc"); diff --git a/src/celengine/glsupport.h b/src/celengine/glsupport.h index dce2d25483..9cfbcb0e4f 100644 --- a/src/celengine/glsupport.h +++ b/src/celengine/glsupport.h @@ -49,7 +49,6 @@ extern CELAPI bool OES_texture_border_clamp; //NOSONAR extern CELAPI bool OES_geometry_shader; //NOSONAR #else extern CELAPI bool ARB_vertex_array_object; //NOSONAR -extern CELAPI bool ARB_framebuffer_object; //NOSONAR #endif extern CELAPI GLint maxPointSize; //NOSONAR extern CELAPI GLint maxTextureSize; //NOSONAR diff --git a/src/celengine/overlay.h b/src/celengine/overlay.h index f7255b184c..8257a717ed 100644 --- a/src/celengine/overlay.h +++ b/src/celengine/overlay.h @@ -10,6 +10,7 @@ #pragma once +#include #include #include #include @@ -60,6 +61,13 @@ class Overlay void print(std::string_view); + template + void print(const std::locale& loc, std::string_view format, const T&... args) + { + static_assert(sizeof...(args) > 0); + print(fmt::format(loc, format, args...)); + } + template void print(std::string_view format, const T&... args) { diff --git a/src/celengine/render.cpp b/src/celengine/render.cpp index ff1a09f9c7..29cdc1283e 100644 --- a/src/celengine/render.cpp +++ b/src/celengine/render.cpp @@ -4811,8 +4811,6 @@ Renderer::createShadowFBO() void Renderer::setShadowMapSize(unsigned size) { - if (!FramebufferObject::isSupported()) - return; m_shadowMapSize = std::min(size, static_cast(gl::maxTextureSize)); if (m_shadowFBO != nullptr && m_shadowMapSize == m_shadowFBO->width()) return; diff --git a/src/celengine/texture.cpp b/src/celengine/texture.cpp index 12953ff4df..7742e14b40 100644 --- a/src/celengine/texture.cpp +++ b/src/celengine/texture.cpp @@ -485,10 +485,6 @@ ImageTexture::ImageTexture(const Image& img, } bool genMipmaps = mipmap && !precomputedMipMaps; -#ifndef GL_ES - if (genMipmaps && !FramebufferObject::isSupported()) - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); -#endif if (mipmap) { @@ -511,7 +507,7 @@ ImageTexture::ImageTexture(const Image& img, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); #endif } - if (genMipmaps && FramebufferObject::isSupported()) + if (genMipmaps) glGenerateMipmap(GL_TEXTURE_2D); alpha = img.hasAlpha(); @@ -689,25 +685,9 @@ TiledTexture::TiledTexture(const Image& img, } } + LoadMiplessTexture(*tile, GL_TEXTURE_2D); if (mipmap) - { - if (FramebufferObject::isSupported()) - { - LoadMiplessTexture(*tile, GL_TEXTURE_2D); - glGenerateMipmap(GL_TEXTURE_2D); - } -#ifndef GL_ES - else - { - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - LoadMiplessTexture(*tile, GL_TEXTURE_2D); - } -#endif - } - else - { - LoadMiplessTexture(*tile, GL_TEXTURE_2D); - } + glGenerateMipmap(GL_TEXTURE_2D); } } } @@ -810,29 +790,17 @@ CubeMap::CubeMap(celestia::util::array_view faces) : bool genMipmaps = mipmap && !precomputedMipMaps; -#if !defined(GL_ES) - if (genMipmaps && !FramebufferObject::isSupported()) - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); -#endif - for (int i = 0; i < 6; i++) { auto targetFace = static_cast(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); const Image* face = faces[i]; - if (mipmap) - { - if (precomputedMipMaps) - LoadMipmapSet(*face, targetFace); - else - LoadMiplessTexture(*face, targetFace); - } + if (mipmap && precomputedMipMaps) + LoadMipmapSet(*face, targetFace); else - { LoadMiplessTexture(*face, targetFace); - } } - if (genMipmaps && FramebufferObject::isSupported()) + if (genMipmaps) glGenerateMipmap(GL_TEXTURE_CUBE_MAP); } diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index f5effddf15..e443160da3 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -33,6 +33,9 @@ #include #include +#if FMT_VERSION < 90000 +#include +#endif #include #include @@ -1206,12 +1209,12 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) Vector3d v = sim->getSelection().getPosition(sim->getTime()).offsetFromKm(sim->getObserver().getPosition()); int hours, mins; float secs; - string buf; + std::string buf; if (v.norm() >= 86400.0_c) { // Light travel time in years, if >= 1day - buf = fmt::sprintf(_("Light travel time: %.4f yr"), - astro::kilometersToLightYears(v.norm())); + buf = fmt::format(loc, _("Light travel time: {:.4f} yr"), + astro::kilometersToLightYears(v.norm())); } else { @@ -1219,13 +1222,13 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) getLightTravelDelay(v.norm(), hours, mins, secs); if (hours == 0) { - buf = fmt::sprintf(_("Light travel time: %d min %.1f s"), - mins, secs); + buf = fmt::format(loc, _("Light travel time: {} min {:.1f} s"), + mins, secs); } else { - buf = fmt::sprintf(_("Light travel time: %d h %d min %.1f s"), - hours, mins, secs); + buf = fmt::format(loc, _("Light travel time: {} h {} min {:.1f} s"), + hours, mins, secs); } } flash(buf, 2.0); @@ -1378,9 +1381,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) sim->setTimeScale(sim->getTimeScale() / CoarseTimeScaleFactor); else sim->setTimeScale(sim->getTimeScale() / FineTimeScaleFactor); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Time rate: %.6g"), sim->getTimeScale()); // XXX %'.12g - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Time rate: {:.6g}"), sim->getTimeScale()); // XXX %'.12g flash(buf); } break; @@ -1393,9 +1394,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) sim->setTimeScale(sim->getTimeScale() * CoarseTimeScaleFactor); else sim->setTimeScale(sim->getTimeScale() * FineTimeScaleFactor); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Time rate: %.6g"), sim->getTimeScale()); // XXX %'.12g - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Time rate: {:.6g}"), sim->getTimeScale()); flash(buf); } break; @@ -1511,10 +1510,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) { setFaintest(sim->getFaintestVisible() - 0.2f); notifyWatchers(FaintestChanged); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Magnitude limit: %.2f"), - sim->getFaintestVisible()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Magnitude limit: {:.2f}"), sim->getFaintestVisible()); flash(buf); } } @@ -1522,10 +1518,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) { renderer->setFaintestAM45deg(renderer->getFaintestAM45deg() - 0.1f); setFaintestAutoMag(); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Auto magnitude limit at 45 degrees: %.2f"), - renderer->getFaintestAM45deg()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Auto magnitude limit at 45 degrees: {:.2f}"), renderer->getFaintestAM45deg()); flash(buf); } break; @@ -1542,10 +1535,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) { setFaintest(sim->getFaintestVisible() + 0.2f); notifyWatchers(FaintestChanged); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Magnitude limit: %.2f"), - sim->getFaintestVisible()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Magnitude limit: {:.2f}"), sim->getFaintestVisible()); flash(buf); } } @@ -1553,10 +1543,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) { renderer->setFaintestAM45deg(renderer->getFaintestAM45deg() + 0.1f); setFaintestAutoMag(); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Auto magnitude limit at 45 degrees: %.2f"), - renderer->getFaintestAM45deg()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Auto magnitude limit at 45 degrees: {:.2f}"), renderer->getFaintestAM45deg()); flash(buf); } break; @@ -1572,10 +1559,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) else renderer->setAmbientLightLevel(0.0f); notifyWatchers(AmbientLightChanged); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Ambient light level: %.2f"), - renderer->getAmbientLightLevel()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Ambient light level: {:.2f}"), renderer->getAmbientLightLevel()); flash(buf); } break; @@ -1587,10 +1571,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) else renderer->setAmbientLightLevel(1.0f); notifyWatchers(AmbientLightChanged); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf(_("Ambient light level: %.2f"), - renderer->getAmbientLightLevel()); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Ambient light level: {:.2f}"), renderer->getAmbientLightLevel()); flash(buf); } break; @@ -1598,9 +1579,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) case '(': { Galaxy::decreaseLightGain(); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf("%s: %3.0f %%", _("Light gain"), Galaxy::getLightGain() * 100.0f); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Light gain: {:3.0f} %"), Galaxy::getLightGain() * 100.0f); flash(buf); notifyWatchers(GalaxyLightGainChanged); } @@ -1609,9 +1588,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers) case ')': { Galaxy::increaseLightGain(); - setlocale(LC_NUMERIC, ""); - string buf = fmt::sprintf("%s: %3.0f %%", _("Light gain"), Galaxy::getLightGain() * 100.0f); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Light gain: {:3.0f} %"), Galaxy::getLightGain() * 100.0f); flash(buf); notifyWatchers(GalaxyLightGainChanged); } @@ -2300,9 +2277,8 @@ void CelestiaCore::updateFOV(float newFOV, const std::optional if ((renderer->getRenderFlags() & Renderer::ShowAutoMag) != 0) { setFaintestAutoMag(); - setlocale(LC_NUMERIC, ""); - flash(fmt::sprintf(_("Magnitude limit: %.2f"), sim->getFaintestVisible())); - setlocale(LC_NUMERIC, "C"); + auto buf = fmt::format(loc, _("Magnitude limit: {:.2f}"), sim->getFaintestVisible()); + flash(buf); } } @@ -2368,7 +2344,7 @@ bool CelestiaCore::initSimulation(const fs::path& configFileName, } } - hud = std::make_unique(); + hud = std::make_unique(loc); #ifdef CELX initLuaHook(progressNotifier); diff --git a/src/celestia/celestiacore.h b/src/celestia/celestiacore.h index d95094ce9e..e0a658da84 100644 --- a/src/celestia/celestiacore.h +++ b/src/celestia/celestiacore.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -425,6 +426,8 @@ class CelestiaCore // : public Watchable Simulation* sim{ nullptr }; Renderer* renderer{ nullptr }; + std::locale loc{ "" }; + celestia::WindowMetrics metrics; std::unique_ptr hud; diff --git a/src/celestia/data/space.celestiaproject.Celestia.metainfo.xml.in b/src/celestia/data/space.celestiaproject.Celestia.metainfo.xml.in new file mode 100644 index 0000000000..a110c6c747 --- /dev/null +++ b/src/celestia/data/space.celestiaproject.Celestia.metainfo.xml.in @@ -0,0 +1,48 @@ + + + + @METAINFO_ID@ + MIT + GPL-2.0+ + @METAINFO_NAME@ + Celestia Project + + Celestia Project + + Explore the universe + +

+ Celestia provides photo-realistic, real-time, three-dimensional viewing of + the Solar System, the Galaxy and the Universe. +

+

+ It is an easy to use, freely-distributed, multi-platform, open source, + software package which has become a valuable tool for astronomy education. + Used in homes, schools, museums and planetariums around the world, it also + is used as a visualization tool by space mission designers. +

+
+ @METAINFO_DESKTOP@ + https://celestiaproject.space + + + + + + Cassini–Huygens in orbit around Saturn + https://celestiaproject.space/images/gallery/cassini.jpg + + + Earth + https://celestiaproject.space/images/gallery/earth.jpg + + + Europa in orbit around Jupiter with Io inbetween + https://celestiaproject.space/images/gallery/europa.jpg + + + Proxima Centuri with solar filaments + https://celestiaproject.space/images/gallery/proxima.png + + +
diff --git a/src/celestia/gtk/actions.cpp b/src/celestia/gtk/actions.cpp index dfb4f24dfe..70e9d99741 100644 --- a/src/celestia/gtk/actions.cpp +++ b/src/celestia/gtk/actions.cpp @@ -11,15 +11,12 @@ */ #include +#include #include #include #include #include -#ifdef GNOME -#include -#endif /* GNOME */ - #include #include #include @@ -45,40 +42,164 @@ #include "dialog-time.h" #include "dialog-tour.h" -#ifdef GNOME -#include "settings-gconf.h" -#else #include "settings-file.h" -#endif /* GNOME */ -using namespace std; +namespace celestia::gtk +{ + +namespace +{ + +/* Script opening helper called by actionOpenScript() */ +void +openScript(const char* filename, AppData* app) +{ + /* Modified From Win32 HandleOpenScript */ + if (filename) + { + /* If you got here, a path and file has been specified. + * filename contains full path to specified file. */ + app->core->runScript(filename); + } +} + +/* Image capturing helper called by actionCaptureImage() */ +void +captureImage(const char* filename, AppData* app) +{ + ContentType type = DetermineFileType(filename); + if (type != ContentType::JPEG && type != ContentType::PNG) + { + GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Please use a name ending in '.jpg' or '.png'.")); + gtk_dialog_run(GTK_DIALOG(errBox)); + gtk_widget_destroy(errBox); + return; + } + + if (!app->core->saveScreenShot(filename)) + { + GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Error writing captured image.")); + gtk_dialog_run(GTK_DIALOG(errBox)); + gtk_widget_destroy(errBox); + } +} -/* Declarations: Action Helpers */ -static void openScript(const char* filename, AppData* app); -static void captureImage(const char* filename, AppData* app); +/* Image capturing helper called by actionCaptureImage() */ #ifdef USE_FFMPEG -static void captureMovie(const char* filename, const int resolution[], float fps, - AVCodecID codec, float bitrate, AppData* app); +void +captureMovie(const char* filename, const int resolution[], float fps, + AVCodecID codec, float bitrate, AppData* app) +{ + auto* movieCapture = new FFMPEGCapture(app->renderer); + movieCapture->setVideoCodec(codec); + movieCapture->setBitRate(bitrate); + if (codec == AV_CODEC_ID_H264) + movieCapture->setEncoderOptions(app->core->getConfig()->x264EncoderOptions); + else + movieCapture->setEncoderOptions(app->core->getConfig()->ffvhEncoderOptions); + + bool success = movieCapture->start(filename, resolution[0], resolution[1], fps); + if (success) + { + app->core->initMovieCapture(movieCapture); + } + else + { + delete movieCapture; + + GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "Error initializing movie capture."); + gtk_dialog_run(GTK_DIALOG(errBox)); + gtk_widget_destroy(errBox); + } +} #endif -static void textInfoDialog(const char *txt, const char *title, AppData* app); -static void setRenderFlag(AppData* a, uint64_t flag, gboolean state); -static void setOrbitMask(AppData* a, int mask, gboolean state); -static void setLabelMode(AppData* a, int mode, gboolean state); + +/* Runs a dialog that displays text; should be replaced at some point with + a more elegant solution. */ +void +textInfoDialog(const char *txt, const char *title, AppData* app) +{ + /* I would use a gnome_message_box dialog for this, except they don't seem + * to notice that the texts are so big that they create huge windows, and + * would work better with a scrolled window. Deon */ + GtkWidget* dialog = gtk_dialog_new_with_buttons(title, + GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + + GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL); + GtkWidget* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_box_pack_start(GTK_BOX(content_area), scrolled_window, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_show(scrolled_window); + + GtkWidget *text = gtk_label_new(txt); + gtk_widget_modify_font(text, pango_font_description_from_string("mono")); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), GTK_WIDGET(text)); + gtk_widget_show(text); + + gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 400); /* Absolute Size, urghhh */ + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); + + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +/* Calculates and sets the render-flag int */ +void +setRenderFlag(AppData* a, std::uint64_t flag, gboolean state) +{ + std::uint64_t rf = (a->renderer->getRenderFlags() & ~flag) | (state ? flag : 0); + a->renderer->setRenderFlags(rf); +} + +/* Calculates and sets the orbit-mask int */ +void +setOrbitMask(AppData* a, int mask, gboolean state) +{ + int om = (a->renderer->getOrbitMask() & ~mask) | (state ? mask : 0); + a->renderer->setOrbitMask(om); +} + +/* Calculates and sets the label-mode int */ +void +setLabelMode(AppData* a, int mode, gboolean state) +{ + int lm = (a->renderer->getLabelMode() & ~mode) | (state ? mode : 0); + a->renderer->setLabelMode(lm); +} #ifdef USE_FFMPEG -static const int MovieSizes[][2] = -{ - { 160, 120 }, - { 320, 240 }, - { 640, 480 }, - { 720, 480 }, - { 720, 576 }, - { 1024, 768 }, - { 1280, 720 }, - { 1920, 1080 } +using MovieSize = std::array; + +constexpr std::array MovieSizes +{ + MovieSize{ 160, 120 }, + MovieSize{ 320, 240 }, + MovieSize{ 640, 480 }, + MovieSize{ 720, 480 }, + MovieSize{ 720, 576 }, + MovieSize{ 1024, 768 }, + MovieSize{ 1280, 720 }, + MovieSize{ 1920, 1080 } }; -static const float MovieFramerates[] = { 15.0f, 23.976f, 24.0f, 25.0f, 29.97f, 30.0f, 60.0f }; +constexpr std::array MovieFramerates{ 15.0f, 23.976f, 24.0f, 25.0f, 29.97f, 30.0f, 60.0f }; struct MovieCodec { @@ -86,13 +207,14 @@ struct MovieCodec const char *codecDesc; }; -static MovieCodec MovieCodecs[2] = +constexpr std::array MovieCodecs { - { AV_CODEC_ID_FFVHUFF, N_("Lossless") }, - { AV_CODEC_ID_H264, N_("Lossy (H.264)") } + MovieCodec{ AV_CODEC_ID_FFVHUFF, N_("Lossless") }, + MovieCodec{ AV_CODEC_ID_H264, N_("Lossy (H.264)") } }; -static void insert_text_event(GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data) +void +insert_text_event(GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data) { for (int i = 0; i < length; i++) { @@ -105,8 +227,11 @@ static void insert_text_event(GtkEditable *editable, const gchar *text, gint len } #endif +} // end unnamed namespace + /* File -> Copy URL */ -void actionCopyURL(GtkAction*, AppData* app) +void +actionCopyURL(GtkAction*, AppData* app) { GtkClipboard* cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); CelestiaState appState(app->core); @@ -117,7 +242,8 @@ void actionCopyURL(GtkAction*, AppData* app) /* File -> Open URL */ -void actionOpenURL(GtkAction*, AppData* app) +void +actionOpenURL(GtkAction*, AppData* app) { GtkWidget* dialog = gtk_dialog_new_with_buttons("Enter cel:// URL", GTK_WINDOW(app->mainWindow), @@ -145,7 +271,8 @@ void actionOpenURL(GtkAction*, AppData* app) /* File -> Open Script... */ -void actionOpenScript(GtkAction*, AppData* app) +void +actionOpenScript(GtkAction*, AppData* app) { GtkWidget* fs = gtk_file_chooser_dialog_new("Open Script.", GTK_WINDOW(app->mainWindow), @@ -183,9 +310,9 @@ void actionOpenScript(GtkAction*, AppData* app) gtk_widget_destroy(fs); } - /* File -> Capture Image... */ -void actionCaptureImage(GtkAction*, AppData* app) +void +actionCaptureImage(GtkAction*, AppData* app) { GtkWidget* fs = gtk_file_chooser_dialog_new("Save Image to File", GTK_WINDOW(app->mainWindow), @@ -224,7 +351,8 @@ void actionCaptureImage(GtkAction*, AppData* app) } /* File -> Capture Movie... */ -void actionCaptureMovie(GtkAction*, AppData* app) +void +actionCaptureMovie(GtkAction*, AppData* app) { #ifdef USE_FFMPEG // TODO: The menu item should be disable so that the user doesn't even @@ -318,7 +446,7 @@ void actionCaptureMovie(GtkAction*, AppData* app) int fridx = gtk_combo_box_get_active(GTK_COMBO_BOX(frcombo)); int vcidx = gtk_combo_box_get_active(GTK_COMBO_BOX(vccombo)); const gchar *brtext = gtk_entry_get_text(GTK_ENTRY(brentry)); - const int *resolution = MovieSizes[vsidx]; + const int *resolution = MovieSizes[vsidx].data(); float fps = MovieFramerates[fridx]; AVCodecID codec = MovieCodecs[vcidx].codecId; float bitrate = 400000; @@ -346,9 +474,9 @@ void actionCaptureMovie(GtkAction*, AppData* app) #endif } - /* File -> Run Demo... */ -void actionRunDemo(GtkAction*, AppData* app) +void +actionRunDemo(GtkAction*, AppData* app) { const auto& demoScriptFile = app->core->getConfig()->paths.demoScriptFile; if (!demoScriptFile.empty()) @@ -358,32 +486,27 @@ void actionRunDemo(GtkAction*, AppData* app) } } - -void actionQuit(GtkAction*, AppData* app) +void +actionQuit(GtkAction*, AppData* app) { - #ifdef GNOME - saveSettingsGConf(app); - #else saveSettingsFile(app); - #endif /* GNOME */ - gtk_main_quit(); } - -void actionSelectSol(GtkAction*, AppData* app) +void +actionSelectSol(GtkAction*, AppData* app) { app->core->charEntered('H'); } - -void actionTourGuide(GtkAction*, AppData* app) +void +actionTourGuide(GtkAction*, AppData* app) { dialogTourGuide(app); } - -void actionSearchObject(GtkAction*, AppData* app) +void +actionSearchObject(GtkAction*, AppData* app) { GtkWidget* dialog = gtk_dialog_new_with_buttons("Select Object", GTK_WINDOW(app->mainWindow), @@ -420,109 +543,105 @@ void actionSearchObject(GtkAction*, AppData* app) gtk_widget_destroy(GTK_WIDGET(dialog)); } - -void actionGotoObject(GtkAction*, AppData* app) +void +actionGotoObject(GtkAction*, AppData* app) { dialogGotoObject(app); } - -void actionCenterSelection(GtkAction*, AppData* app) +void +actionCenterSelection(GtkAction*, AppData* app) { app->core->charEntered('c'); } - -void actionGotoSelection(GtkAction*, AppData* app) +void +actionGotoSelection(GtkAction*, AppData* app) { app->core->charEntered('G'); } - -void actionFollowSelection(GtkAction*, AppData* app) +void +actionFollowSelection(GtkAction*, AppData* app) { app->core->charEntered('F'); } - -void actionSyncSelection(GtkAction*, AppData* app) +void +actionSyncSelection(GtkAction*, AppData* app) { app->core->charEntered('Y'); } - -void actionTrackSelection(GtkAction*, AppData* app) +void +actionTrackSelection(GtkAction*, AppData* app) { app->core->charEntered('T'); } - -void actionSystemBrowser(GtkAction*, AppData* app) +void +actionSystemBrowser(GtkAction*, AppData* app) { dialogSolarBrowser(app); } - -void actionStarBrowser(GtkAction*, AppData* app) +void +actionStarBrowser(GtkAction*, AppData* app) { dialogStarBrowser(app); } - -void actionEclipseFinder(GtkAction*, AppData* app) +void +actionEclipseFinder(GtkAction*, AppData* app) { dialogEclipseFinder(app); } - -void actionTimeFaster(GtkAction*, AppData* app) +void +actionTimeFaster(GtkAction*, AppData* app) { app->core->charEntered('L'); } - -void actionTimeSlower(GtkAction*, AppData* app) +void +actionTimeSlower(GtkAction*, AppData* app) { app->core->charEntered('K'); } - -void actionTimeFreeze(GtkAction*, AppData* app) +void +actionTimeFreeze(GtkAction*, AppData* app) { app->core->charEntered(' '); } - -void actionTimeReal(GtkAction*, AppData* app) +void +actionTimeReal(GtkAction*, AppData* app) { app->core->charEntered('\\'); } - -void actionTimeReverse(GtkAction*, AppData* app) +void +actionTimeReverse(GtkAction*, AppData* app) { app->core->charEntered('J'); } - -void actionTimeSet(GtkAction*, AppData* app) +void +actionTimeSet(GtkAction*, AppData* app) { dialogSetTime(app); } - -void actionTimeLocal(GtkAction* action, AppData* app) +void +actionTimeLocal(GtkAction* action, AppData* app) { app->showLocalTime = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); updateTimeZone(app, app->showLocalTime); - - #ifdef GNOME - gconf_client_set_bool(app->client, "/apps/celestia/showLocalTime", app->showLocalTime, NULL); - #endif /* GNOME */ } - -void actionViewerSize(GtkAction*, AppData* app) +void +actionViewerSize(GtkAction*, AppData* app) { GtkWidget* dialog; int newX, currentX, currentY, winX, winY, screenX, i = 1, position = -1; @@ -552,12 +671,12 @@ void actionViewerSize(GtkAction*, AppData* app) { if (position == -1 && resolutions[i-1] < currentX && resolutions[i] >= currentX) { - sprintf(res, "%d x %d (current)", currentX, currentY); + std::sprintf(res, "%d x %d (current)", currentX, currentY); position = i - 1; } else if (resolutions[i] < screenX) { - sprintf(res, "%d x %d", resolutions[i], int(0.75 * resolutions[i])); + std::sprintf(res, "%d x %d", resolutions[i], int(0.75 * resolutions[i])); i++; } else @@ -592,8 +711,8 @@ void actionViewerSize(GtkAction*, AppData* app) gtk_widget_destroy(GTK_WIDGET(dialog)); } - -void actionFullScreen(GtkAction* action, AppData* app) +void +actionFullScreen(GtkAction* action, AppData* app) { int positionX, positionY; app->fullScreen = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); @@ -616,110 +735,98 @@ void actionFullScreen(GtkAction* action, AppData* app) /* Enable/Disable the Viewer Size action */ gtk_action_set_sensitive(gtk_action_group_get_action(app->agMain, "ViewerSize"), !app->fullScreen); - - #ifdef GNOME - gconf_client_set_bool(app->client, "/apps/celestia/fullScreen", app->fullScreen, NULL); - #endif } - -void actionViewOptions(GtkAction*, AppData* app) +void +actionViewOptions(GtkAction*, AppData* app) { dialogViewOptions(app); } - -void actionStarsMore(GtkAction*, AppData* app) +void +actionStarsMore(GtkAction*, AppData* app) { app->core->charEntered(']'); - - #ifdef GNOME - gconf_client_set_float(app->client, "/apps/celestia/visualMagnitude", app->simulation->getFaintestVisible(), NULL); - #endif } - -void actionStarsFewer(GtkAction*, AppData* app) +void +actionStarsFewer(GtkAction*, AppData* app) { app->core->charEntered('['); - - #ifdef GNOME - gconf_client_set_float(app->client, "/apps/celestia/visualMagnitude", app->simulation->getFaintestVisible(), NULL); - #endif } - -void actionMenuBarVisible(GtkToggleAction* action, AppData* app) +void +actionMenuBarVisible(GtkToggleAction* action, AppData* app) { g_object_set(G_OBJECT(app->mainMenu), "visible", gtk_toggle_action_get_active(action), NULL); } - -void actionMultiSplitH(GtkAction*, AppData* app) +void +actionMultiSplitH(GtkAction*, AppData* app) { app->core->splitView(celestia::View::HorizontalSplit); } - -void actionMultiSplitV(GtkAction*, AppData* app) +void +actionMultiSplitV(GtkAction*, AppData* app) { app->core->splitView(celestia::View::VerticalSplit); } - -void actionMultiCycle(GtkAction*, AppData* app) +void +actionMultiCycle(GtkAction*, AppData* app) { /* Pass a Tab character */ app->core->charEntered('\011'); } - -void actionMultiDelete(GtkAction*, AppData* app) +void +actionMultiDelete(GtkAction*, AppData* app) { app->core->deleteView(); } - -void actionMultiSingle(GtkAction*, AppData* app) +void +actionMultiSingle(GtkAction*, AppData* app) { app->core->singleView(); } - -void actionMultiShowFrames(GtkToggleAction* action, AppData* app) +void +actionMultiShowFrames(GtkToggleAction* action, AppData* app) { app->core->setFramesVisible(gtk_toggle_action_get_active(action)); } - -void actionMultiShowActive(GtkToggleAction* action, AppData* app) +void +actionMultiShowActive(GtkToggleAction* action, AppData* app) { app->core->setActiveFrameVisible(gtk_toggle_action_get_active(action)); } - -void actionMultiSyncTime(GtkToggleAction* action, AppData* app) +void +actionMultiSyncTime(GtkToggleAction* action, AppData* app) { app->simulation->setSyncTime(gtk_toggle_action_get_active(action)); } - -void actionHelpControls(GtkAction*, AppData* app) +void +actionHelpControls(GtkAction*, AppData* app) { char *txt = readFromFile("controls.txt"); textInfoDialog(txt, "Mouse and Keyboard Controls", app); g_free(txt); } - -void actionHelpOpenGL(GtkAction*, AppData* app) +void +actionHelpOpenGL(GtkAction*, AppData* app) { - string s = Helper::getRenderInfo(app->renderer); + std::string s = Helper::getRenderInfo(app->renderer); textInfoDialog(s.c_str(), "Renderer Info", app); } - -void actionHelpAbout(GtkAction*, AppData* app) +void +actionHelpAbout(GtkAction*, AppData* app) { const gchar* authors[] = { "Chris Laurel ", @@ -738,9 +845,9 @@ void actionHelpAbout(GtkAction*, AppData* app) GdkPixbuf *logo = gdk_pixbuf_new_from_file ("celestia-logo.png", NULL); - string comments = fmt::format("GTK+ Front-End, built using gtk+ version {}.{}", - GTK_MAJOR_VERSION, - GTK_MINOR_VERSION); + std::string comments = fmt::format("GTK+ Front-End, built using gtk+ version {}.{}", + GTK_MAJOR_VERSION, + GTK_MINOR_VERSION); gtk_show_about_dialog(GTK_WINDOW(app->mainWindow), "title", _("About Celestia"), @@ -756,490 +863,332 @@ void actionHelpAbout(GtkAction*, AppData* app) g_object_unref(logo); } - -void actionVerbosity(GtkRadioAction* action, GtkRadioAction*, AppData* app) +void +actionVerbosity(GtkRadioAction* action, GtkRadioAction*, AppData* app) { int value = gtk_radio_action_get_current_value(action); app->core->setHudDetail(value); - - #ifdef GNOME - gconf_client_set_int(app->client, "/apps/celestia/verbosity", value, NULL); - #endif } - -void actionStarStyle(GtkRadioAction* action, GtkRadioAction*, AppData* app) +void +actionStarStyle(GtkRadioAction* action, GtkRadioAction*, AppData* app) { int value = gtk_radio_action_get_current_value(action); app->renderer->setStarStyle((Renderer::StarStyle)value); - - #ifdef GNOME - gconf_client_set_int(app->client, "/apps/celestia/starStyle", value, NULL); - #endif } - -void actionAmbientLight(GtkRadioAction* action, GtkRadioAction*, AppData* app) +void +actionAmbientLight(GtkRadioAction* action, GtkRadioAction*, AppData* app) { float value = amLevels[gtk_radio_action_get_current_value(action)]; app->renderer->setAmbientLightLevel(value); - - #ifdef GNOME - gconf_client_set_float(app->client, "/apps/celestia/ambientLight", value, NULL); - #endif } /* Render-Flag Actions */ -void actionRenderAA(GtkToggleAction* action, AppData* app) +void +actionRenderAA(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowSmoothLines, gtk_toggle_action_get_active(action)); } - -void actionRenderAtmospheres(GtkToggleAction* action, AppData* app) +void +actionRenderAtmospheres(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowAtmospheres, gtk_toggle_action_get_active(action)); } - -void actionRenderAutoMagnitude(GtkToggleAction* action, AppData* app) +void +actionRenderAutoMagnitude(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowAutoMag, gtk_toggle_action_get_active(action)); } - -void actionRenderCelestialGrid(GtkToggleAction* action, AppData* app) +void +actionRenderCelestialGrid(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowCelestialSphere, gtk_toggle_action_get_active(action)); } - -void actionRenderClouds(GtkToggleAction* action, AppData* app) +void +actionRenderClouds(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowCloudMaps, gtk_toggle_action_get_active(action)); } - -void actionRenderCometTails(GtkToggleAction* action, AppData* app) +void +actionRenderCometTails(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowCometTails, gtk_toggle_action_get_active(action)); } - -void actionRenderConstellationBoundaries(GtkToggleAction* action, AppData* app) +void +actionRenderConstellationBoundaries(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowBoundaries, gtk_toggle_action_get_active(action)); } - -void actionRenderConstellations(GtkToggleAction* action, AppData* app) +void +actionRenderConstellations(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowDiagrams, gtk_toggle_action_get_active(action)); } - -void actionRenderEclipticGrid(GtkToggleAction* action, AppData* app) +void +actionRenderEclipticGrid(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowEclipticGrid, gtk_toggle_action_get_active(action)); } - -void actionRenderEclipseShadows(GtkToggleAction* action, AppData* app) +void +actionRenderEclipseShadows(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowEclipseShadows, gtk_toggle_action_get_active(action)); } - -void actionRenderGalacticGrid(GtkToggleAction* action, AppData* app) +void +actionRenderGalacticGrid(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowGalacticGrid, gtk_toggle_action_get_active(action)); } - -void actionRenderGalaxies(GtkToggleAction* action, AppData* app) +void +actionRenderGalaxies(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowGalaxies, gtk_toggle_action_get_active(action)); } - -void actionRenderGlobulars(GtkToggleAction* action, AppData* app) +void +actionRenderGlobulars(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowGlobulars, gtk_toggle_action_get_active(action)); } - -void actionRenderHorizontalGrid(GtkToggleAction* action, AppData* app) +void +actionRenderHorizontalGrid(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowHorizonGrid, gtk_toggle_action_get_active(action)); } - -void actionRenderMarkers(GtkToggleAction* action, AppData* app) +void +actionRenderMarkers(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowMarkers, gtk_toggle_action_get_active(action)); } - -void actionRenderNebulae(GtkToggleAction* action, AppData* app) +void +actionRenderNebulae(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowNebulae, gtk_toggle_action_get_active(action)); } - -void actionRenderNightLights(GtkToggleAction* action, AppData* app) +void +actionRenderNightLights(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowNightMaps, gtk_toggle_action_get_active(action)); } - -void actionRenderOpenClusters(GtkToggleAction* action, AppData* app) +void +actionRenderOpenClusters(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowOpenClusters, gtk_toggle_action_get_active(action)); } - -void actionRenderOrbits(GtkToggleAction* action, AppData* app) +void +actionRenderOrbits(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowOrbits, gtk_toggle_action_get_active(action)); } -void actionRenderFadingOrbits(GtkToggleAction* action, AppData* app) +void +actionRenderFadingOrbits(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowFadingOrbits, gtk_toggle_action_get_active(action)); } - -void actionRenderPlanets(GtkToggleAction* action, AppData* app) +void +actionRenderPlanets(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowPlanets, gtk_toggle_action_get_active(action)); } - -void actionRenderDwarfPlanets(GtkToggleAction* action, AppData* app) +void +actionRenderDwarfPlanets(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowDwarfPlanets, gtk_toggle_action_get_active(action)); } - -void actionRenderMoons(GtkToggleAction* action, AppData* app) +void +actionRenderMoons(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowMoons, gtk_toggle_action_get_active(action)); } - -void actionRenderMinorMoons(GtkToggleAction* action, AppData* app) +void +actionRenderMinorMoons(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowMinorMoons, gtk_toggle_action_get_active(action)); } - -void actionRenderAsteroids(GtkToggleAction* action, AppData* app) +void +actionRenderAsteroids(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowAsteroids, gtk_toggle_action_get_active(action)); } - -void actionRenderComets(GtkToggleAction* action, AppData* app) +void +actionRenderComets(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowComets, gtk_toggle_action_get_active(action)); } - -void actionRenderSpacecrafts(GtkToggleAction* action, AppData* app) +void +actionRenderSpacecrafts(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowSpacecrafts, gtk_toggle_action_get_active(action)); } - -void actionRenderPlanetRings(GtkToggleAction* action, AppData* app) +void +actionRenderPlanetRings(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowPlanetRings, gtk_toggle_action_get_active(action)); } -void actionRenderRingShadows(GtkToggleAction* action, AppData* app) +void +actionRenderRingShadows(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowRingShadows, gtk_toggle_action_get_active(action)); } - -void actionRenderStars(GtkToggleAction* action, AppData* app) +void +actionRenderStars(GtkToggleAction* action, AppData* app) { setRenderFlag(app, Renderer::ShowStars, gtk_toggle_action_get_active(action)); } - -void actionOrbitAsteroids(GtkToggleAction* action, AppData* app) +void +actionOrbitAsteroids(GtkToggleAction* action, AppData* app) { setOrbitMask(app, Body::Asteroid, gtk_toggle_action_get_active(action)); } - -void actionOrbitComets(GtkToggleAction* action, AppData* app) +void +actionOrbitComets(GtkToggleAction* action, AppData* app) { setOrbitMask(app, Body::Comet, gtk_toggle_action_get_active(action)); } - -void actionOrbitMoons(GtkToggleAction* action, AppData* app) +void +actionOrbitMoons(GtkToggleAction* action, AppData* app) { setOrbitMask(app, Body::Moon, gtk_toggle_action_get_active(action)); } - -void actionOrbitPlanets(GtkToggleAction* action, AppData* app) +void +actionOrbitPlanets(GtkToggleAction* action, AppData* app) { setOrbitMask(app, Body::Planet, gtk_toggle_action_get_active(action)); } - -void actionOrbitSpacecraft(GtkToggleAction* action, AppData* app) +void +actionOrbitSpacecraft(GtkToggleAction* action, AppData* app) { setOrbitMask(app, Body::Spacecraft, gtk_toggle_action_get_active(action)); } - -void actionLabelAsteroids(GtkToggleAction* action, AppData* app) +void +actionLabelAsteroids(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::AsteroidLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelComets(GtkToggleAction* action, AppData* app) +void +actionLabelComets(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::CometLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelConstellations(GtkToggleAction* action, AppData* app) +void +actionLabelConstellations(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::ConstellationLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelGalaxies(GtkToggleAction* action, AppData* app) +void +actionLabelGalaxies(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::GalaxyLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelGlobulars(GtkToggleAction* action, AppData* app) +void +actionLabelGlobulars(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::GlobularLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelLocations(GtkToggleAction* action, AppData* app) +void +actionLabelLocations(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::LocationLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelMoons(GtkToggleAction* action, AppData* app) +void +actionLabelMoons(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::MoonLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelMinorMoons(GtkToggleAction* action, AppData* app) +void +actionLabelMinorMoons(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::MinorMoonLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelNebulae(GtkToggleAction* action, AppData* app) +void +actionLabelNebulae(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::NebulaLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelOpenClusters(GtkToggleAction* action, AppData* app) +void +actionLabelOpenClusters(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::OpenClusterLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelPlanets(GtkToggleAction* action, AppData* app) +void +actionLabelPlanets(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::PlanetLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelDwarfPlanets(GtkToggleAction* action, AppData* app) +void +actionLabelDwarfPlanets(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::DwarfPlanetLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelSpacecraft(GtkToggleAction* action, AppData* app) +void +actionLabelSpacecraft(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::SpacecraftLabels, gtk_toggle_action_get_active(action)); } - -void actionLabelStars(GtkToggleAction* action, AppData* app) +void +actionLabelStars(GtkToggleAction* action, AppData* app) { setLabelMode(app, Renderer::StarLabels, gtk_toggle_action_get_active(action)); } - -/* Script opening helper called by actionOpenScript() */ -static void openScript(const char* filename, AppData* app) -{ - /* Modified From Win32 HandleOpenScript */ - if (filename) - { - /* If you got here, a path and file has been specified. - * filename contains full path to specified file. */ - app->core->runScript(filename); - } -} - - -/* Image capturing helper called by actionCaptureImage() */ -static void captureImage(const char* filename, AppData* app) -{ - ContentType type = DetermineFileType(filename); - if (type != ContentType::JPEG && type != ContentType::PNG) - { - GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Please use a name ending in '.jpg' or '.png'.")); - gtk_dialog_run(GTK_DIALOG(errBox)); - gtk_widget_destroy(errBox); - return; - } - - if (!app->core->saveScreenShot(filename)) - { - GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "Error writing captured image."); - gtk_dialog_run(GTK_DIALOG(errBox)); - gtk_widget_destroy(errBox); - } -} - -/* Image capturing helper called by actionCaptureImage() */ -#ifdef USE_FFMPEG -static void captureMovie(const char* filename, const int resolution[], float fps, - AVCodecID codec, float bitrate, AppData* app) -{ - auto* movieCapture = new FFMPEGCapture(app->renderer); - movieCapture->setVideoCodec(codec); - movieCapture->setBitRate(bitrate); - if (codec == AV_CODEC_ID_H264) - movieCapture->setEncoderOptions(app->core->getConfig()->x264EncoderOptions); - else - movieCapture->setEncoderOptions(app->core->getConfig()->ffvhEncoderOptions); - - bool success = movieCapture->start(filename, resolution[0], resolution[1], fps); - if (success) - { - app->core->initMovieCapture(movieCapture); - } - else - { - delete movieCapture; - - GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "Error initializing movie capture."); - gtk_dialog_run(GTK_DIALOG(errBox)); - gtk_widget_destroy(errBox); - } -} -#endif - -/* Runs a dialog that displays text; should be replaced at some point with - a more elegant solution. */ -static void textInfoDialog(const char *txt, const char *title, AppData* app) -{ - /* I would use a gnome_message_box dialog for this, except they don't seem - * to notice that the texts are so big that they create huge windows, and - * would work better with a scrolled window. Deon */ - GtkWidget* dialog = gtk_dialog_new_with_buttons(title, - GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); - - GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL); - GtkWidget* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - gtk_box_pack_start(GTK_BOX(content_area), scrolled_window, TRUE, TRUE, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_widget_show(scrolled_window); - - GtkWidget *text = gtk_label_new(txt); - gtk_widget_modify_font(text, pango_font_description_from_string("mono")); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), GTK_WIDGET(text)); - gtk_widget_show(text); - - gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 400); /* Absolute Size, urghhh */ - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - - -/* Calculates and sets the render-flag int */ -static void setRenderFlag(AppData* a, uint64_t flag, gboolean state) -{ - uint64_t rf = (a->renderer->getRenderFlags() & ~flag) | (state ? flag : 0); - a->renderer->setRenderFlags(rf); - - #ifdef GNOME - /* Update GConf */ - gcSetRenderFlag(flag, state, a->client); - #endif /* GNOME */ -} - - -/* Calculates and sets the orbit-mask int */ -static void setOrbitMask(AppData* a, int mask, gboolean state) -{ - int om = (a->renderer->getOrbitMask() & ~mask) | (state ? mask : 0); - a->renderer->setOrbitMask(om); - - #ifdef GNOME - /* Update GConf */ - gcSetOrbitMask(mask, state, a->client); - #endif /* GNOME */ -} - - -/* Calculates and sets the label-mode int */ -static void setLabelMode(AppData* a, int mode, gboolean state) -{ - int lm = (a->renderer->getLabelMode() & ~mode) | (state ? mode : 0); - a->renderer->setLabelMode(lm); - - #ifdef GNOME - /* Update GConf */ - gcSetLabelMode(mode, state, a->client); - #endif /* GNOME */ -} - - /* Synchronizes the Label Actions with the state of the core */ -void resyncLabelActions(AppData* app) +void +resyncLabelActions(AppData* app) { - GtkAction* action; - const char* actionName; - /* Simply for readability */ int f = app->renderer->getLabelMode(); for (int i = Renderer::StarLabels; i <= Renderer::GlobularLabels; i *= 2) { + const char* actionName; switch (i) { case Renderer::StarLabels: actionName = "LabelStars"; break; @@ -1257,13 +1206,13 @@ void resyncLabelActions(AppData* app) case Renderer::OpenClusterLabels: actionName = "LabelOpenClusters"; break; case Renderer::GlobularLabels: actionName = "LabelGlobulars"; break; case Renderer::I18nConstellationLabels: /* Not used yet */ - default: actionName = NULL; + default: actionName = nullptr; break; } - if (actionName != NULL) + if (actionName != nullptr) { /* Get the action */ - action = gtk_action_group_get_action(app->agLabel, actionName); + GtkAction* action = gtk_action_group_get_action(app->agLabel, actionName); /* The current i anded with the labelMode gives state of flag */ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & f)); @@ -1271,22 +1220,20 @@ void resyncLabelActions(AppData* app) } } - /* Synchronizes the Render Actions with the state of the core */ -void resyncRenderActions(AppData* app) +void +resyncRenderActions(AppData* app) { - GtkAction* action; - const char* actionName; - /* Simply for readability */ - uint64_t rf = app->renderer->getRenderFlags(); + const std::uint64_t rf = app->renderer->getRenderFlags(); /* Unlike the other interfaces, which go through each menu item and set * the corresponding renderFlag, we go the other way and set the menu * based on the renderFlag. Last one is ShowPlanetRings. */ - for (uint64_t i = Renderer::ShowStars; i <= Renderer::ShowPlanetRings; i *= 2) + for (std::uint64_t i = Renderer::ShowStars; i <= Renderer::ShowPlanetRings; i *= 2) { + const char* actionName; switch (i) { case Renderer::ShowStars: actionName = "RenderStars"; break; @@ -1313,22 +1260,22 @@ void resyncRenderActions(AppData* app) case Renderer::ShowAutoMag: actionName = "RenderAutoMagnitude"; break; case Renderer::ShowCometTails: actionName = "RenderCometTails"; break; case Renderer::ShowMarkers: actionName = "RenderMarkers"; break; - case Renderer::ShowPartialTrajectories: actionName = NULL; break; /* Not useful yet */ + case Renderer::ShowPartialTrajectories: actionName = nullptr; break; /* Not useful yet */ case Renderer::ShowNebulae: actionName = "RenderNebulae"; break; case Renderer::ShowOpenClusters: actionName = "RenderOpenClusters"; break; case Renderer::ShowGlobulars: actionName = "RenderGlobulars"; break; - case Renderer::ShowCloudShadows: actionName = NULL; break; /* Not implemented yet */ + case Renderer::ShowCloudShadows: actionName = nullptr; break; /* Not implemented yet */ case Renderer::ShowGalacticGrid: actionName = "RenderGalacticGrid"; break; case Renderer::ShowEclipticGrid: actionName = "RenderEclipticGrid"; break; case Renderer::ShowHorizonGrid: actionName = "RenderHorizontalGrid"; break; - case Renderer::ShowEcliptic: actionName = NULL; break; /* Not implemented yet */ - default: actionName = NULL; + case Renderer::ShowEcliptic: actionName = nullptr; break; /* Not implemented yet */ + default: actionName = nullptr; break; } - if (actionName != NULL) + if (actionName != nullptr) { /* Get the action */ - action = gtk_action_group_get_action(app->agRender, actionName); + GtkAction* action = gtk_action_group_get_action(app->agRender, actionName); /* The current i anded with the renderFlags gives state of flag */ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & rf) != 0); @@ -1336,18 +1283,16 @@ void resyncRenderActions(AppData* app) } } - /* Synchronizes the Orbit Actions with the state of the core */ -void resyncOrbitActions(AppData* app) +void +resyncOrbitActions(AppData* app) { - GtkAction* action; - const char* actionName; - /* Simply for readability */ int om = app->renderer->getOrbitMask(); for (int i = Body::Planet; i <= Body::Spacecraft; i *= 2) { + const char* actionName; switch (i) { case Body::Planet: actionName = "OrbitPlanets"; break; @@ -1355,13 +1300,13 @@ void resyncOrbitActions(AppData* app) case Body::Asteroid: actionName = "OrbitAsteroids"; break; case Body::Comet: actionName = "OrbitComets"; break; case Body::Spacecraft: actionName = "OrbitSpacecraft"; break; - default: actionName = NULL; + default: actionName = nullptr; break; } - if (actionName != NULL) + if (actionName != nullptr) { /* Get the action */ - action = gtk_action_group_get_action(app->agOrbit, actionName); + GtkAction* action = gtk_action_group_get_action(app->agOrbit, actionName); /* The current i anded with the orbitMask gives state of flag */ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), (i & om)); @@ -1369,13 +1314,11 @@ void resyncOrbitActions(AppData* app) } } - /* Synchronizes the Verbosity Actions with the state of the core */ -void resyncVerbosityActions(AppData* app) +void +resyncVerbosityActions(AppData* app) { - GtkAction* action; const char* actionName; - switch (app->core->getHudDetail()) { case 0: actionName = "HudNone"; break; @@ -1385,22 +1328,22 @@ void resyncVerbosityActions(AppData* app) } /* Get the action, set the widget */ - action = gtk_action_group_get_action(app->agVerbosity, actionName); + GtkAction* action = gtk_action_group_get_action(app->agVerbosity, actionName); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } - /* Synchronizes the TimeZone Action with the state of the core */ -void resyncTimeZoneAction(AppData* app) +void +resyncTimeZoneAction(AppData* app) { /* Get the action, set the widget */ GtkAction* action = gtk_action_group_get_action(app->agMain, "TimeLocal"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), app->showLocalTime); } - /* Synchronizes the Ambient Light Actions with the state of the core */ -void resyncAmbientActions(AppData* app) +void +resyncAmbientActions(AppData* app) { GtkAction* action; @@ -1417,17 +1360,11 @@ void resyncAmbientActions(AppData* app) action = gtk_action_group_get_action(app->agAmbient, "AmbientMedium"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); - - #ifdef GNOME - /* The action callback only occurs when one of the None/Low/Medium barriers - * is surpassed, so an update is forced. */ - gconf_client_set_float(app->client, "/apps/celestia/ambientLight", ambient, NULL); - #endif } - /* Synchronizes the Verbosity Actions with the state of the core */ -void resyncStarStyleActions(AppData* app) +void +resyncStarStyleActions(AppData* app) { GtkAction* action; const char* actionName; @@ -1445,22 +1382,18 @@ void resyncStarStyleActions(AppData* app) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); } - /* Placeholder for when galaxy brightness is added as an action */ -void resyncGalaxyGainActions(AppData* app) +void +resyncGalaxyGainActions(AppData* app) { - #ifdef GNOME - float gain = Galaxy::getLightGain(); - gconf_client_set_float(app->client, "/apps/celestia/galaxyLightGain", gain, NULL); - #endif + /* no-op */ } - /* Synchronizes the Texture Resolution with the state of the core */ -void resyncTextureResolutionActions(AppData* app) +void +resyncTextureResolutionActions(AppData* app) { - #ifdef GNOME - int resolution = app->renderer->getResolution(); - gconf_client_set_int(app->client, "/apps/celestia/textureResolution", resolution, NULL); - #endif /* GNOME */ + /* no-op */ } + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/actions.h b/src/celestia/gtk/actions.h index 45dc6ff667..1fb5c51693 100644 --- a/src/celestia/gtk/actions.h +++ b/src/celestia/gtk/actions.h @@ -16,6 +16,8 @@ #include "common.h" +namespace celestia::gtk +{ /* Main Actions */ void actionCopyURL(GtkAction*, AppData*); @@ -133,10 +135,7 @@ void resyncStarStyleActions(AppData* app); void resyncGalaxyGainActions(AppData* app); void resyncTextureResolutionActions(AppData* app); - /* Information for the about box */ -#ifdef GNOME -#define FRONTEND "GNOME" -#else #define FRONTEND "GTK+" -#endif + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/common.cpp b/src/celestia/gtk/common.cpp index 758e918e1d..6e668e7bdf 100644 --- a/src/celestia/gtk/common.cpp +++ b/src/celestia/gtk/common.cpp @@ -21,28 +21,28 @@ #include "common.h" -using namespace std; - -namespace astro = celestia::astro; +namespace celestia::gtk +{ /* Returns the offset of the timezone at date */ -gint tzOffsetAtDate(const astro::Date& date) +gint +tzOffsetAtDate(const astro::Date& date) { #ifdef WIN32 /* This does not correctly handle DST. Unfortunately, no way to find * out what UTC offset is at specified date in Windows */ return -timezone; #else - time_t time = (time_t)astro::julianDateToSeconds(date - astro::Date(1970, 1, 1)); - struct tm *d = localtime(&time); + std::time_t time = (time_t)astro::julianDateToSeconds(date - astro::Date(1970, 1, 1)); + struct std::tm *d = localtime(&time); - return (gint)d->tm_gmtoff; + return static_cast(d->tm_gmtoff); #endif } - /* Updates the time zone in the core based on valid timezone data */ -void updateTimeZone(AppData* app, gboolean local) +void +updateTimeZone(AppData* app, gboolean local) { if (local) /* Always base current time zone on simulation date */ @@ -51,9 +51,9 @@ void updateTimeZone(AppData* app, gboolean local) app->core->setTimeZoneBias(0); } - /* Creates a button. Used in several dialogs. */ -gint buttonMake(GtkWidget *hbox, const char *txt, GCallback func, gpointer data) +gint +buttonMake(GtkWidget *hbox, const char *txt, GCallback func, gpointer data) { GtkWidget* button = gtk_button_new_with_label(txt); @@ -63,11 +63,11 @@ gint buttonMake(GtkWidget *hbox, const char *txt, GCallback func, gpointer data) return 0; } - /* creates a group of radioButtons. Used in several dialogs. */ -void makeRadioItems(const char* const *labels, GtkWidget *box, GCallback sigFunc, GtkToggleButton **gads, gpointer data) +void +makeRadioItems(const char* const *labels, GtkWidget *box, GCallback sigFunc, GtkToggleButton **gads, gpointer data) { - GSList *group = NULL; + GSList *group = nullptr; for (gint i=0; labels[i]; i++) { @@ -83,17 +83,17 @@ void makeRadioItems(const char* const *labels, GtkWidget *box, GCallback sigFunc gtk_widget_show (button); g_signal_connect(G_OBJECT(button), "pressed", sigFunc, GINT_TO_POINTER(i)); - if (data != NULL) + if (data != nullptr) g_object_set_data(G_OBJECT(button), "data", data); } } - /* Gets the contents of a file and sanitizes formatting */ -char *readFromFile(const char *fname) +char* +readFromFile(const char *fname) { - ifstream textFile(fname, ios::in); - string s(""); + std::ifstream textFile(fname, std::ios::in); + std::string s(""); if (!textFile.is_open()) { s = "Unable to open file '"; @@ -114,9 +114,9 @@ char *readFromFile(const char *fname) return g_strdup(s.c_str()); } - /* Returns width of the non-fullscreen window */ -int getWinWidth(AppData* app) +int +getWinWidth(AppData* app) { if (app->fullScreen) return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(app->mainWindow), "sizeX")); @@ -126,9 +126,9 @@ int getWinWidth(AppData* app) return allocation.width; } - /* Returns height of the non-fullscreen window */ -int getWinHeight(AppData* app) +int +getWinHeight(AppData* app) { if (app->fullScreen) return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(app->mainWindow), "sizeY")); @@ -138,9 +138,9 @@ int getWinHeight(AppData* app) return allocation.height; } - /* Returns X-position of the non-fullscreen window */ -int getWinX(AppData* app) +int +getWinX(AppData* app) { int positionX; @@ -148,14 +148,14 @@ int getWinX(AppData* app) return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(app->mainWindow), "positionX")); else { - gtk_window_get_position(GTK_WINDOW(app->mainWindow), &positionX, NULL); + gtk_window_get_position(GTK_WINDOW(app->mainWindow), &positionX, nullptr); return positionX; } } - /* Returns Y-position of the non-fullscreen window */ -int getWinY(AppData* app) +int +getWinY(AppData* app) { int positionY; @@ -163,14 +163,14 @@ int getWinY(AppData* app) return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(app->mainWindow), "positionY")); else { - gtk_window_get_position(GTK_WINDOW(app->mainWindow), NULL, &positionY); + gtk_window_get_position(GTK_WINDOW(app->mainWindow), nullptr, &positionY); return positionY; } } - /* Sanitizes and sets Ambient Light */ -void setSaneAmbientLight(AppData* app, float value) +void +setSaneAmbientLight(AppData* app, float value) { if (value < 0.0 || value > 1.0) value = amLevels[1]; /* Default to "Low" */ @@ -178,9 +178,9 @@ void setSaneAmbientLight(AppData* app, float value) app->renderer->setAmbientLightLevel(value); } - /* Sanitizes and sets Visual Magnitude */ -void setSaneVisualMagnitude(AppData* app, float value) +void +setSaneVisualMagnitude(AppData* app, float value) { if (value < 0.0 || value > 100.0) value = 8.5f; /* Default from Simulation::Simulation() */ @@ -188,9 +188,9 @@ void setSaneVisualMagnitude(AppData* app, float value) app->simulation->setFaintestVisible(value); } - /* Sanitizes and sets Galaxy Light Gain */ -void setSaneGalaxyLightGain(float value) +void +setSaneGalaxyLightGain(float value) { if (value < 0.0 || value > 1.0) value = 0.0f; /* Default */ @@ -198,9 +198,9 @@ void setSaneGalaxyLightGain(float value) Galaxy::setLightGain(value); } - /* Sanitizes and sets Distance Limit */ -void setSaneDistanceLimit(AppData* app, int value) +void +setSaneDistanceLimit(AppData* app, int value) { if (value < 0 || value > 1000000) value = 1000000; /* Default to maximum */ @@ -209,7 +209,8 @@ void setSaneDistanceLimit(AppData* app, int value) } /* Sanitizes and sets HUD Verbosity */ -void setSaneVerbosity(AppData* app, int value) +void +setSaneVerbosity(AppData* app, int value) { if (value < 0 || value > 2) value = 1; /* Default to "Terse" */ @@ -217,9 +218,9 @@ void setSaneVerbosity(AppData* app, int value) app->core->setHudDetail(value); } - /* Sanitizes and sets Star Style */ -void setSaneStarStyle(AppData* app, Renderer::StarStyle value) +void +setSaneStarStyle(AppData* app, Renderer::StarStyle value) { if (value < Renderer::FuzzyPointStars || value > Renderer::ScaledDiscStars) value = Renderer::FuzzyPointStars; @@ -227,9 +228,9 @@ void setSaneStarStyle(AppData* app, Renderer::StarStyle value) app->renderer->setStarStyle(value); } - /* Sanitizes and sets Texture Resolution */ -void setSaneTextureResolution(AppData* app, int value) +void +setSaneTextureResolution(AppData* app, int value) { if (value < 0 || value > MultiResTexture::kTextureResolution) value = medres; /* Default to "Medium" */ @@ -237,19 +238,19 @@ void setSaneTextureResolution(AppData* app, int value) app->renderer->setResolution(value); } - /* Sanitizes and sets Altername Surface Name */ -void setSaneAltSurface(AppData* app, char* value) +void +setSaneAltSurface(AppData* app, char* value) { - if (value == NULL) + if (value == nullptr) value = (char*)""; app->simulation->getActiveObserver()->setDisplayedSurface(value); } - /* Sanitizes and sets Window Size */ -void setSaneWinSize(AppData* app, int x, int y) +void +setSaneWinSize(AppData* app, int x, int y) { int screenX = gdk_screen_get_width(gdk_screen_get_default()); int screenY = gdk_screen_get_height(gdk_screen_get_default()); @@ -263,9 +264,9 @@ void setSaneWinSize(AppData* app, int x, int y) gtk_widget_set_size_request(app->glArea, x, y); } - /* Sanitizes and sets Window Position */ -void setSaneWinPosition(AppData* app, int x, int y) +void +setSaneWinPosition(AppData* app, int x, int y) { int screenX = gdk_screen_get_width(gdk_screen_get_default()); int screenY = gdk_screen_get_height(gdk_screen_get_default()); @@ -277,9 +278,11 @@ void setSaneWinPosition(AppData* app, int x, int y) } } - /* Sets default render flags. Exists because the defaults are a little lame. */ -void setDefaultRenderFlags(AppData* app) +void +setDefaultRenderFlags(AppData* app) { app->renderer->setRenderFlags(Renderer::DefaultRenderFlags); } + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/common.h b/src/celestia/gtk/common.h index bff281bd62..bd9c2466b4 100644 --- a/src/celestia/gtk/common.h +++ b/src/celestia/gtk/common.h @@ -13,16 +13,15 @@ #pragma once #include +#include #include -#ifdef GNOME -#include -#endif /* GNOME */ - #include #include #include +namespace celestia::gtk +{ typedef struct _AppData AppData; struct _AppData { @@ -48,11 +47,7 @@ struct _AppData { GtkActionGroup* agAmbient; /* Settings */ - #ifdef GNOME - GConfClient* client; - #else GKeyFile* settingsFile; - #endif /* GNOME */ /* Ready to render? */ gboolean bReady; @@ -96,9 +91,8 @@ void setSaneWinSize(AppData* app, int x, int y); void setSaneWinPosition(AppData* app, int x, int y); void setDefaultRenderFlags(AppData* app); - /* Constants used throughout */ -const char * const monthOptions[] = +constexpr inline std::array monthOptions { "January", "February", @@ -112,17 +106,17 @@ const char * const monthOptions[] = "October", "November", "December", - NULL + static_cast(nullptr), }; -static const float amLevels[] = +constexpr inline std::array amLevels { - 0.0, - 0.1, - 0.25 + 0.0f, + 0.1f, + 0.25f, }; -static const int resolutions[] = +constexpr inline std::array resolutions = { 0, /* Must start with 0 */ 640, @@ -136,4 +130,6 @@ static const int resolutions[] = }; /* This is the spacing used for widgets throughout the program */ -#define CELSPACING 8 +constexpr inline gint CELSPACING = 8; + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/data/CMakeLists.txt b/src/celestia/gtk/data/CMakeLists.txt index 94b1e42cd8..43f30b6594 100644 --- a/src/celestia/gtk/data/CMakeLists.txt +++ b/src/celestia/gtk/data/CMakeLists.txt @@ -1,15 +1,20 @@ +set(METAINFO_ID "space.celestiaproject.Celestia-gtk") +set(METAINFO_NAME "Celestia (GTK)") +set(METAINFO_DESKTOP "celestia-gtk.desktop") +configure_file("../../data/space.celestiaproject.Celestia.metainfo.xml.in" "${METAINFO_ID}.metainfo.xml") + install( FILES celestiaui.xml celestia-logo.png DESTINATION "${DATADIR}" COMPONENT gtkgui ) install( - FILES celestia-gtk.desktop + FILES "${METAINFO_DESKTOP}" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications" COMPONENT gtkgui ) install( - FILES space.celestia.celestia_gtk.metainfo.xml + FILES "${METAINFO_ID}.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo" COMPONENT gtkgui ) diff --git a/src/celestia/gtk/data/space.celestia.celestia_gtk.metainfo.xml b/src/celestia/gtk/data/space.celestia.celestia_gtk.metainfo.xml deleted file mode 100644 index f53a22cf35..0000000000 --- a/src/celestia/gtk/data/space.celestia.celestia_gtk.metainfo.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - space.celestia.celestia_gtk - MIT - GPL-2.0+ - Celestia (GTK) - Explore the universe - -

- Celestia provides photo-realistic, real-time, three-dimensional viewing of - the Solar System, the Galaxy and the Universe. -

-

- It is an easy to use, freely-distributed, multi-platform, open source, - software package which has become a valuable tool for astronomy education. - Used in homes, schools, museums and planetariums around the world, it also - is used as a visualization tool by space mission designers. -

-
- celestia-gtk.desktop - https://celestiaproject.space - - https://celestiaproject.space/images/gallery/cassini.jpg - https://celestiaproject.space/images/gallery/earth.jpg - https://celestiaproject.space/images/gallery/europa.jpg - https://celestiaproject.space/images/gallery/proxima.png - -
diff --git a/src/celestia/gtk/dialog-eclipse.cpp b/src/celestia/gtk/dialog-eclipse.cpp index 828e21c653..d78d2d3998 100644 --- a/src/celestia/gtk/dialog-eclipse.cpp +++ b/src/celestia/gtk/dialog-eclipse.cpp @@ -10,6 +10,13 @@ * $Id: dialog-eclipse.cpp,v 1.2 2005-12-10 06:34:21 suwalski Exp $ */ +#include +#include +#include +#include + +#include + #include #include @@ -22,190 +29,82 @@ #include "dialog-eclipse.h" #include "common.h" -using namespace Eigen; -using namespace std; - -namespace astro = celestia::astro; -namespace math = celestia::math; - -/* Definitions: Callbacks */ -static void calDateSelect(GtkCalendar *calendar, GtkToggleButton *button); -static void showCalPopup(GtkToggleButton *button, EclipseData *ed); -static gint eclipseGoto(GtkButton*, EclipseData* ed); -static gint eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed); -static void eclipseCompute(GtkButton* button, EclipseData* ed); -static void eclipseBodySelect(GtkComboBox* comboBox, EclipseData* ed); -static void eclipseTypeSelect(GtkComboBox* comboBox, EclipseData* ed); -static void listEclipseSelect(GtkTreeSelection* sel, EclipseData* ed); -static void eclipseDestroy(GtkWidget* w, gint, EclipseData* ed); - -/* Definitions: Helpers */ -static void setButtonDateString(GtkToggleButton *button, int year, int month, int day); - - -/* ENTRY: Navigation -> Eclipse Finder */ -void dialogEclipseFinder(AppData* app) +namespace celestia::gtk { - EclipseData* ed = g_new0(EclipseData, 1); - selDate* d1 = g_new0(selDate, 1); - selDate* d2 = g_new0(selDate, 1); - ed->d1 = d1; - ed->d2 = d2; - ed->app = app; - ed->eclipseList = NULL; - ed->eclipseListStore = NULL; - ed->type = Eclipse::Solar; - ed->body = eclipsePlanetTitles[0]; - ed->sel = NULL; - - ed->window = GTK_DIALOG(gtk_dialog_new_with_buttons("Eclipse Finder", - GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_OK, - NULL)); - gtk_window_set_modal(GTK_WINDOW(ed->window), FALSE); - - GtkWidget *mainbox = gtk_dialog_get_content_area(GTK_DIALOG(ed->window)); - gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING); - - GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_ALWAYS); - gtk_box_pack_start(GTK_BOX(mainbox), scrolled_win, TRUE, TRUE, 0); - - /* Create listbox list. - * Six invisible ints at the end to hold actual time. - * This will save string parsing like in KDE version. - * Last field holds pointer to selected Body. */ - ed->eclipseListStore = gtk_list_store_new(12, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_INT, - G_TYPE_POINTER); - ed->eclipseList = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ed->eclipseListStore)); - - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ed->eclipseList), TRUE); - gtk_container_add(GTK_CONTAINER(scrolled_win), ed->eclipseList); - - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - /* Add the columns */ - for (int i=0; i<5; i++) { - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(eclipseTitles[i], renderer, "text", i, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(ed->eclipseList), column); - } - - /* Set up callback for when an eclipse is selected */ - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ed->eclipseList)); - g_signal_connect(selection, "changed", G_CALLBACK(listEclipseSelect), ed); - - /* From now on, it's the bottom-of-the-window controls */ - GtkWidget *label; - GtkWidget *hbox; - - /* -------------------------------- */ - hbox = gtk_hbox_new(FALSE, CELSPACING); - - label = gtk_label_new("Find"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - GtkWidget *menuTypeBox = gtk_combo_box_text_new(); - gtk_box_pack_start(GTK_BOX(hbox), menuTypeBox, FALSE, FALSE, 0); - label = gtk_label_new("eclipse on"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - GtkWidget* menuBodyBox = gtk_combo_box_text_new(); - gtk_box_pack_start(GTK_BOX(hbox), menuBodyBox, FALSE, FALSE, 0); - - gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); - /* -------------------------------- */ - hbox = gtk_hbox_new(FALSE, CELSPACING); - - label = gtk_label_new("From"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - /* Get current date */ - astro::Date datenow(app->simulation->getTime()); - - /* Set current time */ - ed->d1->year = datenow.year - 1; - ed->d1->month = datenow.month; - ed->d1->day = datenow.day; - - /* Set time a year from now */ - ed->d2->year = ed->d1->year + 2; - ed->d2->month = ed->d1->month; - ed->d2->day = ed->d1->day; +namespace +{ - GtkWidget* date1Button = gtk_toggle_button_new(); - setButtonDateString(GTK_TOGGLE_BUTTON(date1Button), ed->d1->year, ed->d1->month, ed->d1->day); - g_object_set_data(G_OBJECT(date1Button), "eclipsedata", ed->d1); - gtk_box_pack_start(GTK_BOX(hbox), date1Button, FALSE, FALSE, 0); +/* Local Data Structures */ +/* Date selection data type */ +typedef struct _selDate selDate; +struct _selDate { + int year; + int month; + int day; +}; - label = gtk_label_new("to"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); +typedef struct _EclipseData EclipseData; +struct _EclipseData { + AppData* app; - GtkWidget* date2Button = gtk_toggle_button_new(); - setButtonDateString(GTK_TOGGLE_BUTTON(date2Button), ed->d2->year, ed->d2->month, ed->d2->day); - g_object_set_data(G_OBJECT(date2Button), "eclipsedata", ed->d2); - gtk_box_pack_start(GTK_BOX(hbox), date2Button, FALSE, FALSE, 0); + /* Start Time */ + selDate* d1; - gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); - /* -------------------------------- */ + /* End Time */ + selDate* d2; - /* Common Buttons */ - hbox = gtk_hbox_new(TRUE, CELSPACING); - if (buttonMake(hbox, "Compute", (GCallback)eclipseCompute, ed)) - return; - if (buttonMake(hbox, "Set Date and Go to Planet", (GCallback)eclipseGoto, ed)) - return; - gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); + int type; + const char* body; + GtkTreeSelection* sel; - /* Set up the drop-down boxes */ - for (int i = 0; eclipseTypeTitles[i] != NULL; i++) - { - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menuTypeBox), eclipseTypeTitles[i]); - } - gtk_combo_box_set_active(GTK_COMBO_BOX(menuTypeBox), 0); + GtkWidget *eclipseList; + GtkListStore *eclipseListStore; - for (int i = 0; eclipsePlanetTitles[i] != NULL; i++) - { - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menuBodyBox), eclipsePlanetTitles[i]); - } - gtk_combo_box_set_active(GTK_COMBO_BOX(menuBodyBox), 0); + GtkDialog* window; +}; - /* Hook up all the signals */ - g_signal_connect(G_OBJECT(menuTypeBox), "changed", G_CALLBACK(eclipseTypeSelect), ed); - g_signal_connect(G_OBJECT(menuBodyBox), "changed", G_CALLBACK(eclipseBodySelect), ed); +constexpr std::array eclipseTitles +{ + "Planet", + "Satellite", + "Date", + "Start", + "End", + static_cast(nullptr), +}; + +constexpr std::array eclipseTypeTitles +{ + "solar", + "moon", + static_cast(nullptr), +}; - /* Double-click handler */ - g_signal_connect(G_OBJECT(ed->eclipseList), "button-press-event", G_CALLBACK(eclipse2Click), ed); +constexpr std::array eclipsePlanetTitles +{ + "Earth", + "Jupiter", + "Saturn", + "Uranus", + "Neptune", + "Pluto", + static_cast(nullptr), +}; - g_signal_connect(G_OBJECT(date1Button), "toggled", G_CALLBACK(showCalPopup), ed); - g_signal_connect(G_OBJECT(date2Button), "toggled", G_CALLBACK(showCalPopup), ed); - g_signal_connect(ed->window, "response", G_CALLBACK(eclipseDestroy), ed); +/* HELPER: set a date string in a button */ +void +setButtonDateString(GtkToggleButton *button, int year, int month, int day) +{ + char date[50]; + std::sprintf(date, "%d %s %d", day, monthOptions[month - 1], year); - gtk_widget_set_size_request(GTK_WIDGET(ed->window), -1, 400); /* Absolute Size, urghhh */ - gtk_widget_show_all(GTK_WIDGET(ed->window)); + gtk_button_set_label(GTK_BUTTON(button), date); } - /* CALLBACK: When the GtkCalendar date is selected */ -static void calDateSelect(GtkCalendar *calendar, GtkToggleButton *button) +void +calDateSelect(GtkCalendar *calendar, GtkToggleButton *button) { /* Set the selected date */ guint year, month, day; @@ -224,9 +123,9 @@ static void calDateSelect(GtkCalendar *calendar, GtkToggleButton *button) gtk_toggle_button_set_active(button, !gtk_toggle_button_get_active(button)); } - /* CALLBACK: When a button is clicked to show a GtkCalendar */ -static void showCalPopup(GtkToggleButton *button, EclipseData *ed) +void +showCalPopup(GtkToggleButton *button, EclipseData *ed) { GtkWidget* calwindow = GTK_WIDGET(g_object_get_data(G_OBJECT(button), "calendar")); @@ -281,9 +180,9 @@ static void showCalPopup(GtkToggleButton *button, EclipseData *ed) } } - /* CALLBACK: "SetTime/Goto" in Eclipse Finder */ -static gint eclipseGoto(GtkButton*, EclipseData* ed) +gint +eclipseGoto(GtkButton*, EclipseData* ed) { GValue value = { 0, {{0}} }; /* Initialize GValue to 0 */ GtkTreeIter iter; @@ -331,15 +230,15 @@ static gint eclipseGoto(GtkButton*, EclipseData* ed) sim->update(0.0); double distance = target.radius() * 4.0; - sim->gotoLocation(UniversalCoord::Zero().offsetKm(Vector3d::UnitX() * distance), + sim->gotoLocation(UniversalCoord::Zero().offsetKm(Eigen::Vector3d::UnitX() * distance), (math::YRot90Conjugate * math::XRot90Conjugate), 2.5); return TRUE; } - /* CALLBACK: Double-click on the Eclipse Finder Listbox */ -static gint eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed) +gint +eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed) { if (event->type == GDK_2BUTTON_PRESS) { /* Double-click, same as hitting the select and go button */ @@ -349,9 +248,9 @@ static gint eclipse2Click(GtkWidget*, GdkEventButton* event, EclipseData* ed) return FALSE; } - /* CALLBACK: Compute button in Eclipse Finder */ -static void eclipseCompute(GtkButton* button, EclipseData* ed) +void +eclipseCompute(GtkButton* button, EclipseData* ed) { /* Set the cursor to a watch and force redraw */ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(button)), gdk_cursor_new(GDK_WATCH)); @@ -365,7 +264,7 @@ static void eclipseCompute(GtkButton* button, EclipseData* ed) astro::Date to(ed->d2->year, ed->d2->month, ed->d2->day); /* Initialize the eclipse finder */ - vector eclipseListRaw; + std::vector eclipseListRaw; const SolarSystem* sys = ed->app->core->getSimulation()->getNearestSolarSystem(); if (sys != nullptr && sys->getStar()->getIndex() == 0) { @@ -383,9 +282,9 @@ static void eclipseCompute(GtkButton* button, EclipseData* ed) astro::Date start(e.startTime); astro::Date end(e.endTime); - sprintf(d, "%d-%02d-%02d", start.year, start.month, start.day); - sprintf(strStart, "%02d:%02d:%02d", start.hour, start.minute, (int)start.seconds); - sprintf(strEnd, "%02d:%02d:%02d", end.hour, end.minute, (int)end.seconds); + std::sprintf(d, "%d-%02d-%02d", start.year, start.month, start.day); + std::sprintf(strStart, "%02d:%02d:%02d", start.hour, start.minute, (int)start.seconds); + std::sprintf(strEnd, "%02d:%02d:%02d", end.hour, end.minute, (int)end.seconds); /* Set time to middle time so that eclipse it right on earth */ astro::Date timeToSet = (start + end) / 2.0f; @@ -425,9 +324,9 @@ static void eclipseCompute(GtkButton* button, EclipseData* ed) gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(button)), gdk_cursor_new(GDK_LEFT_PTR)); } - /* CALLBACK: When Eclipse Body is selected */ -static void eclipseBodySelect(GtkComboBox* comboBox, EclipseData* ed) +void +eclipseBodySelect(GtkComboBox* comboBox, EclipseData* ed) { int itemIndex = gtk_combo_box_get_active(comboBox); @@ -435,9 +334,9 @@ static void eclipseBodySelect(GtkComboBox* comboBox, EclipseData* ed) ed->body = eclipsePlanetTitles[itemIndex]; } - /* CALLBACK: When Eclipse Type (Solar:Moon) is selected */ -static void eclipseTypeSelect(GtkComboBox* comboBox, EclipseData* ed) +void +eclipseTypeSelect(GtkComboBox* comboBox, EclipseData* ed) { int itemIndex = gtk_combo_box_get_active(comboBox); @@ -449,17 +348,17 @@ static void eclipseTypeSelect(GtkComboBox* comboBox, EclipseData* ed) ed->type = Eclipse::Lunar; } - /* CALLBACK: When Eclipse is selected in Eclipse Finder */ -static void listEclipseSelect(GtkTreeSelection* sel, EclipseData* ed) +void +listEclipseSelect(GtkTreeSelection* sel, EclipseData* ed) { /* Simply set the selection pointer to this data item */ ed->sel = sel; } - /* CALLBACK: Destroy Window */ -static void eclipseDestroy(GtkWidget* w, gint, EclipseData* ed) +void +eclipseDestroy(GtkWidget* w, gint, EclipseData* ed) { gtk_widget_destroy(GTK_WIDGET(w)); g_free(ed->d1); @@ -467,12 +366,167 @@ static void eclipseDestroy(GtkWidget* w, gint, EclipseData* ed) g_free(ed); } +} // end unnamed namespace -/* HELPER: set a date string in a button */ -static void setButtonDateString(GtkToggleButton *button, int year, int month, int day) +/* ENTRY: Navigation -> Eclipse Finder */ +void +dialogEclipseFinder(AppData* app) { - char date[50]; - sprintf(date, "%d %s %d", day, monthOptions[month - 1], year); + EclipseData* ed = g_new0(EclipseData, 1); + selDate* d1 = g_new0(selDate, 1); + selDate* d2 = g_new0(selDate, 1); + ed->d1 = d1; + ed->d2 = d2; + ed->app = app; + ed->eclipseList = NULL; + ed->eclipseListStore = NULL; + ed->type = Eclipse::Solar; + ed->body = eclipsePlanetTitles[0]; + ed->sel = NULL; - gtk_button_set_label(GTK_BUTTON(button), date); + ed->window = GTK_DIALOG(gtk_dialog_new_with_buttons("Eclipse Finder", + GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, + GTK_RESPONSE_OK, + NULL)); + gtk_window_set_modal(GTK_WINDOW(ed->window), FALSE); + + GtkWidget *mainbox = gtk_dialog_get_content_area(GTK_DIALOG(ed->window)); + gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING); + + GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_ALWAYS); + gtk_box_pack_start(GTK_BOX(mainbox), scrolled_win, TRUE, TRUE, 0); + + /* Create listbox list. + * Six invisible ints at the end to hold actual time. + * This will save string parsing like in KDE version. + * Last field holds pointer to selected Body. */ + ed->eclipseListStore = gtk_list_store_new(12, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_POINTER); + ed->eclipseList = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ed->eclipseListStore)); + + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ed->eclipseList), TRUE); + gtk_container_add(GTK_CONTAINER(scrolled_win), ed->eclipseList); + + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + /* Add the columns */ + for (int i=0; i<5; i++) { + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(eclipseTitles[i], renderer, "text", i, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(ed->eclipseList), column); + } + + /* Set up callback for when an eclipse is selected */ + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ed->eclipseList)); + g_signal_connect(selection, "changed", G_CALLBACK(listEclipseSelect), ed); + + /* From now on, it's the bottom-of-the-window controls */ + GtkWidget *label; + GtkWidget *hbox; + + /* -------------------------------- */ + hbox = gtk_hbox_new(FALSE, CELSPACING); + + label = gtk_label_new("Find"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + GtkWidget *menuTypeBox = gtk_combo_box_text_new(); + gtk_box_pack_start(GTK_BOX(hbox), menuTypeBox, FALSE, FALSE, 0); + + label = gtk_label_new("eclipse on"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + GtkWidget* menuBodyBox = gtk_combo_box_text_new(); + gtk_box_pack_start(GTK_BOX(hbox), menuBodyBox, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); + /* -------------------------------- */ + hbox = gtk_hbox_new(FALSE, CELSPACING); + + label = gtk_label_new("From"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + /* Get current date */ + astro::Date datenow(app->simulation->getTime()); + + /* Set current time */ + ed->d1->year = datenow.year - 1; + ed->d1->month = datenow.month; + ed->d1->day = datenow.day; + + /* Set time a year from now */ + ed->d2->year = ed->d1->year + 2; + ed->d2->month = ed->d1->month; + ed->d2->day = ed->d1->day; + + GtkWidget* date1Button = gtk_toggle_button_new(); + setButtonDateString(GTK_TOGGLE_BUTTON(date1Button), ed->d1->year, ed->d1->month, ed->d1->day); + g_object_set_data(G_OBJECT(date1Button), "eclipsedata", ed->d1); + gtk_box_pack_start(GTK_BOX(hbox), date1Button, FALSE, FALSE, 0); + + label = gtk_label_new("to"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + GtkWidget* date2Button = gtk_toggle_button_new(); + setButtonDateString(GTK_TOGGLE_BUTTON(date2Button), ed->d2->year, ed->d2->month, ed->d2->day); + g_object_set_data(G_OBJECT(date2Button), "eclipsedata", ed->d2); + gtk_box_pack_start(GTK_BOX(hbox), date2Button, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); + /* -------------------------------- */ + + /* Common Buttons */ + hbox = gtk_hbox_new(TRUE, CELSPACING); + if (buttonMake(hbox, "Compute", (GCallback)eclipseCompute, ed)) + return; + if (buttonMake(hbox, "Set Date and Go to Planet", (GCallback)eclipseGoto, ed)) + return; + gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); + + /* Set up the drop-down boxes */ + for (int i = 0; eclipseTypeTitles[i] != NULL; i++) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menuTypeBox), eclipseTypeTitles[i]); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(menuTypeBox), 0); + + for (int i = 0; eclipsePlanetTitles[i] != NULL; i++) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menuBodyBox), eclipsePlanetTitles[i]); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(menuBodyBox), 0); + + /* Hook up all the signals */ + g_signal_connect(G_OBJECT(menuTypeBox), "changed", G_CALLBACK(eclipseTypeSelect), ed); + g_signal_connect(G_OBJECT(menuBodyBox), "changed", G_CALLBACK(eclipseBodySelect), ed); + + /* Double-click handler */ + g_signal_connect(G_OBJECT(ed->eclipseList), "button-press-event", G_CALLBACK(eclipse2Click), ed); + + g_signal_connect(G_OBJECT(date1Button), "toggled", G_CALLBACK(showCalPopup), ed); + g_signal_connect(G_OBJECT(date2Button), "toggled", G_CALLBACK(showCalPopup), ed); + g_signal_connect(ed->window, "response", G_CALLBACK(eclipseDestroy), ed); + + gtk_widget_set_size_request(GTK_WIDGET(ed->window), -1, 400); /* Absolute Size, urghhh */ + gtk_widget_show_all(GTK_WIDGET(ed->window)); } + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-eclipse.h b/src/celestia/gtk/dialog-eclipse.h index fe6e0e7601..96eb1563bf 100644 --- a/src/celestia/gtk/dialog-eclipse.h +++ b/src/celestia/gtk/dialog-eclipse.h @@ -17,65 +17,10 @@ #include "common.h" +namespace celestia::gtk +{ /* Entry Function */ void dialogEclipseFinder(AppData* app); - -/* Local Data Structures */ -/* Date selection data type */ -typedef struct _selDate selDate; -struct _selDate { - int year; - int month; - int day; -}; - -typedef struct _EclipseData EclipseData; -struct _EclipseData { - AppData* app; - - /* Start Time */ - selDate* d1; - - /* End Time */ - selDate* d2; - - int type; - const char* body; - GtkTreeSelection* sel; - - GtkWidget *eclipseList; - GtkListStore *eclipseListStore; - - GtkDialog* window; -}; - - -const char * const eclipseTitles[] = -{ - "Planet", - "Satellite", - "Date", - "Start", - "End", - NULL -}; - -const char * const eclipseTypeTitles[] = -{ - "solar", - "moon", - NULL -}; - -const char * const eclipsePlanetTitles[] = -{ - "Earth", - "Jupiter", - "Saturn", - "Uranus", - "Neptune", - "Pluto", - NULL -}; +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-goto.cpp b/src/celestia/gtk/dialog-goto.cpp index 651b058c50..d545f28191 100644 --- a/src/celestia/gtk/dialog-goto.cpp +++ b/src/celestia/gtk/dialog-goto.cpp @@ -10,6 +10,10 @@ * $Id: dialog-goto.cpp,v 1.1 2005-12-06 03:19:35 suwalski Exp $ */ +#include + +#include + #include #include @@ -19,22 +23,134 @@ #include "dialog-goto.h" #include "common.h" -using namespace Eigen; +namespace celestia::gtk +{ + +namespace +{ + +/* Local Data Structures */ +typedef struct _gotoObjectData gotoObjectData; +struct _gotoObjectData { + AppData* app; + + GtkWidget* dialog; + GtkWidget* nameEntry; + GtkWidget* latEntry; + GtkWidget* longEntry; + GtkWidget* distEntry; + + int units; +}; + +constexpr std::array unitLabels +{ + "km", + "radii", + "au", + static_cast(nullptr), +}; + +/* HELPER: Get the float value from one of the GtkEntrys */ +gboolean +GetEntryFloat(GtkWidget* w, float& f) +{ + GtkEntry* entry = GTK_ENTRY(w); + bool tmp; + if (entry == nullptr) + return false; -namespace astro = celestia::astro; -namespace math = celestia::math; + gchar* text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + f = 0.0; + if (text == nullptr) + return false; -/* Declarations: Callbacks */ -static int changeGotoUnits(GtkButton* w, gpointer choice); -static void responseGotoObject(GtkDialog* w, gint response, gotoObjectData* d); + tmp = std::sscanf(text, " %f", &f) == 1; + g_free(text); + return tmp; +} + +/* HELPER: Goes to the object specified by gotoObjectData */ +void +GotoObject(gotoObjectData* gotoObjectDlg) +{ + const gchar* objectName = gtk_entry_get_text(GTK_ENTRY(gotoObjectDlg->nameEntry)); + + if (objectName != nullptr) + { + Simulation* simulation = gotoObjectDlg->app->simulation; + Selection sel = simulation->findObjectFromPath(objectName); + + if (!sel.empty()) + { + simulation->setSelection(sel); + simulation->follow(); + + auto distance = static_cast(sel.radius() * 5.0f); + if (GetEntryFloat(gotoObjectDlg->distEntry, distance)) + { + /* Adjust for km (0), radii (1), au (2) */ + if (gotoObjectDlg->units == 2) + distance = astro::AUtoKilometers(distance); + else if (gotoObjectDlg->units == 1) + distance = distance * (float) sel.radius(); -/* Declarations: Helpers */ -static gboolean GetEntryFloat(GtkWidget* w, float& f); -static void GotoObject(gotoObjectData* gotoObjectDlg); + distance += (float) sel.radius(); + } + + float longitude, latitude; + if (GetEntryFloat(gotoObjectDlg->latEntry, latitude) && + GetEntryFloat(gotoObjectDlg->longEntry, longitude)) + { + simulation->gotoSelectionLongLat(5.0, + distance, + math::degToRad(longitude), + math::degToRad(latitude), + Eigen::Vector3f::UnitY()); + } + else + { + simulation->gotoSelection(5.0, + distance, + Eigen::Vector3f::UnitY(), + ObserverFrame::ObserverLocal); + } + } + } +} + +/* CALLBACK: for km|radii|au in Goto Object dialog */ +int +changeGotoUnits(GtkButton* w, gpointer choice) +{ + gotoObjectData* data = (gotoObjectData *)g_object_get_data(G_OBJECT(w), "data"); + gint selection = GPOINTER_TO_INT(choice); + + data->units = selection; + + return TRUE; +} + +/* CALLBACK: response from this dialog. + * Need this because gtk_dialog_run produces a modal window. */ +void +responseGotoObject(GtkDialog* w, gint response, gotoObjectData* d) +{ + switch (response) { + case GTK_RESPONSE_OK: + GotoObject(d); + break; + case GTK_RESPONSE_CLOSE: + gtk_widget_destroy(GTK_WIDGET(w)); + g_free(d); + } +} +} // end unnamed namespace /* ENTRY: Navigation->Goto Object */ -void dialogGotoObject(AppData* app) +void +dialogGotoObject(AppData* app) { gotoObjectData *data = g_new0(gotoObjectData, 1); data->app = app; @@ -46,17 +162,17 @@ void dialogGotoObject(AppData* app) GTK_RESPONSE_OK, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - NULL); + nullptr); data->nameEntry = gtk_entry_new(); data->latEntry = gtk_entry_new(); data->longEntry = gtk_entry_new(); data->distEntry = gtk_entry_new(); - if (data->dialog == NULL || - data->nameEntry == NULL || - data->latEntry == NULL || - data->longEntry == NULL || - data->distEntry == NULL) + if (data->dialog == nullptr || + data->nameEntry == nullptr || + data->latEntry == nullptr || + data->longEntry == nullptr || + data->distEntry == nullptr) { /* Potential memory leak here ... */ return; @@ -67,15 +183,15 @@ void dialogGotoObject(AppData* app) app->simulation->getSelectionLongLat(distance, longitude, latitude); /* Display information in format appropriate for object */ - if (app->simulation->getSelection().body() != NULL) + if (app->simulation->getSelection().body() != nullptr) { char temp[20]; distance = distance - (double) app->simulation->getSelection().body()->getRadius(); - sprintf(temp, "%.1f", (float)distance); + std::sprintf(temp, "%.1f", (float)distance); gtk_entry_set_text(GTK_ENTRY(data->distEntry), temp); - sprintf(temp, "%.5f", (float)longitude); + std::sprintf(temp, "%.5f", (float)longitude); gtk_entry_set_text(GTK_ENTRY(data->longEntry), temp); - sprintf(temp, "%.5f", (float)latitude); + std::sprintf(temp, "%.5f", (float)latitude); gtk_entry_set_text(GTK_ENTRY(data->latEntry), temp); gtk_entry_set_text(GTK_ENTRY(data->nameEntry), (char*) app->simulation->getSelection().body()->getName().c_str()); } @@ -83,9 +199,9 @@ void dialogGotoObject(AppData* app) GtkWidget* vbox = gtk_dialog_get_content_area(GTK_DIALOG(data->dialog)); gtk_container_set_border_width(GTK_CONTAINER(vbox), CELSPACING); - GtkWidget* align = NULL; - GtkWidget* hbox = NULL; - GtkWidget* label = NULL; + GtkWidget* align = nullptr; + GtkWidget* hbox = nullptr; + GtkWidget* label = nullptr; /* Object name label and entry */ align = gtk_alignment_new(1, 0, 0, 0); @@ -125,7 +241,7 @@ void dialogGotoObject(AppData* app) /* Distance Options */ data->units = 0; hbox = gtk_hbox_new(FALSE, CELSPACING); - makeRadioItems(unitLabels, hbox, G_CALLBACK(changeGotoUnits), NULL, data); + makeRadioItems(unitLabels.data(), hbox, G_CALLBACK(changeGotoUnits), nullptr, data); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); g_signal_connect(data->dialog, "response", @@ -134,97 +250,4 @@ void dialogGotoObject(AppData* app) gtk_widget_show_all(data->dialog); } - -/* CALLBACK: for km|radii|au in Goto Object dialog */ -static int changeGotoUnits(GtkButton* w, gpointer choice) -{ - gotoObjectData* data = (gotoObjectData *)g_object_get_data(G_OBJECT(w), "data"); - gint selection = GPOINTER_TO_INT(choice); - - data->units = selection; - - return TRUE; -} - - -/* CALLBACK: response from this dialog. - * Need this because gtk_dialog_run produces a modal window. */ -static void responseGotoObject(GtkDialog* w, gint response, gotoObjectData* d) -{ - switch (response) { - case GTK_RESPONSE_OK: - GotoObject(d); - break; - case GTK_RESPONSE_CLOSE: - gtk_widget_destroy(GTK_WIDGET(w)); - g_free(d); - } -} - - -/* HELPER: Get the float value from one of the GtkEntrys */ -static gboolean GetEntryFloat(GtkWidget* w, float& f) -{ - GtkEntry* entry = GTK_ENTRY(w); - bool tmp; - if (entry == NULL) - return false; - - gchar* text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); - f = 0.0; - if (text == NULL) - return false; - - tmp = sscanf(text, " %f", &f) == 1; - g_free(text); - return tmp; -} - - -/* HELPER: Goes to the object specified by gotoObjectData */ -static void GotoObject(gotoObjectData* gotoObjectDlg) -{ - const gchar* objectName = gtk_entry_get_text(GTK_ENTRY(gotoObjectDlg->nameEntry)); - - if (objectName != NULL) - { - Simulation* simulation = gotoObjectDlg->app->simulation; - Selection sel = simulation->findObjectFromPath(objectName); - - if (!sel.empty()) - { - simulation->setSelection(sel); - simulation->follow(); - - float distance = (float) (sel.radius() * 5.0f); - if (GetEntryFloat(gotoObjectDlg->distEntry, distance)) - { - /* Adjust for km (0), radii (1), au (2) */ - if (gotoObjectDlg->units == 2) - distance = astro::AUtoKilometers(distance); - else if (gotoObjectDlg->units == 1) - distance = distance * (float) sel.radius(); - - distance += (float) sel.radius(); - } - - float longitude, latitude; - if (GetEntryFloat(gotoObjectDlg->latEntry, latitude) && - GetEntryFloat(gotoObjectDlg->longEntry, longitude)) - { - simulation->gotoSelectionLongLat(5.0, - distance, - math::degToRad(longitude), - math::degToRad(latitude), - Vector3f::UnitY()); - } - else - { - simulation->gotoSelection(5.0, - distance, - Vector3f::UnitY(), - ObserverFrame::ObserverLocal); - } - } - } -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-goto.h b/src/celestia/gtk/dialog-goto.h index 3006040279..4396da5410 100644 --- a/src/celestia/gtk/dialog-goto.h +++ b/src/celestia/gtk/dialog-goto.h @@ -16,29 +16,10 @@ #include "common.h" +namespace celestia::gtk +{ /* Entry Function */ void dialogGotoObject(AppData* app); - -/* Local Data Structures */ -typedef struct _gotoObjectData gotoObjectData; -struct _gotoObjectData { - AppData* app; - - GtkWidget* dialog; - GtkWidget* nameEntry; - GtkWidget* latEntry; - GtkWidget* longEntry; - GtkWidget* distEntry; - - int units; -}; - -static const char * const unitLabels[] = -{ - "km", - "radii", - "au", - NULL -}; +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-options.cpp b/src/celestia/gtk/dialog-options.cpp index eb1c0d57e0..3dede4e4c4 100644 --- a/src/celestia/gtk/dialog-options.cpp +++ b/src/celestia/gtk/dialog-options.cpp @@ -10,34 +10,132 @@ * $Id: dialog-options.cpp,v 1.7 2008-01-21 04:55:19 suwalski Exp $ */ +#include +#include + #include #include "dialog-options.h" #include "common.h" #include "ui.h" +namespace celestia::gtk +{ + +namespace +{ + +/* Local data */ +constexpr int DistanceSliderRange = 10000; +constexpr float MaxDistanceLimit = 1.0e6f; + +constexpr std::array ambientLabels +{ + "None", + "Low", + "Medium", + static_cast(nullptr), +}; + +constexpr std::array infoLabels +{ + "None", + "Terse", + "Verbose", + static_cast(nullptr), +}; + +/* HELPER: Creates check buttons from a GtkActionGroup */ +void +checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box) +{ + for (int i = 0; i < size; i++) + { + GtkAction* action = gtk_action_group_get_action(ag, actions[i].name); + + /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label + * is not set with action proxy. */ + GtkWidget* w = gtk_check_button_new_with_mnemonic(actions[i].label); + + gtk_activatable_set_related_action(GTK_ACTIVATABLE(w), action); + gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0); + } +} + +/* HELPER: Creates toggle (instead of radio) buttons from a GtkActionGroup. + * Cannot be GtkRadioButtons because of GTK limitations/bugs. */ +void +toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box) +{ + for (int i = 0; i < size; i++) + { + GtkAction* action = gtk_action_group_get_action(ag, actions[i].name); + + /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label + * is not set with action proxy. */ + GtkWidget* w = gtk_toggle_button_new_with_mnemonic(actions[i].label); + + gtk_activatable_set_related_action(GTK_ACTIVATABLE(w), action); + gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0); + } +} + +/* HELPER: gives a logarithmic value based on linear value */ +float +makeDistanceLimit(float value) +{ + float logDistanceLimit = value / DistanceSliderRange; + return std::pow(MaxDistanceLimit, logDistanceLimit); +} + +/* CALLBACK: React to changes in the star distance limit slider */ +gint +changeDistanceLimit(GtkRange *slider, AppData* app) +{ + GtkLabel* magLabel = (GtkLabel*)g_object_get_data(G_OBJECT(slider), "valueLabel"); + float limit = makeDistanceLimit(gtk_range_get_value(slider)); + app->renderer->setDistanceLimit(limit); + + char labeltext[16] = "100000 ly"; + sprintf(labeltext, "%ld ly", (long)(limit + 0.5)); + gtk_label_set_text(GTK_LABEL(magLabel), labeltext); + + return TRUE; +} -/* Definitions: Callbacks */ -static gint changeDistanceLimit(GtkRange *slider, AppData* app); -static gint changeTextureResolution(GtkRange *slider, AppData* app); -static gchar* formatTextureSlider(GtkRange*, gdouble value); +/* CALLBACK: React to changes in the texture resolution slider */ +gint +changeTextureResolution(GtkRange *slider, AppData* app) +{ + app->renderer->setResolution((int)gtk_range_get_value(slider)); -/* Definitions: Helpers */ -static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box); -static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box); -static float makeDistanceLimit(float value); + /* Seeing as this is not a GtkAction, kick off the update function */ + resyncTextureResolutionActions(app); + return TRUE; +} -static const int DistanceSliderRange = 10000; -static const float MaxDistanceLimit = 1.0e6f; +/* CALLBACK: Format the label under the texture detail slider */ +gchar* +formatTextureSlider(GtkRange*, gdouble value) +{ + switch ((int)value) { + case 0: return g_strdup("Low"); + case 1: return g_strdup("Medium"); + case 2: return g_strdup("High"); + default: return g_strdup("Error"); + } +} +} // end unnamed namespace /* ENTRY: Options -> View Options... */ -void dialogViewOptions(AppData* app) +void +dialogViewOptions(AppData* app) { /* This dialog is hidden and shown because it is likely to be used a lot * and the actions->widgets operations are fairly intensive. */ - if (app->optionDialog != NULL) + if (app->optionDialog != nullptr) { gtk_window_present(GTK_WINDOW(app->optionDialog)); return; @@ -48,7 +146,7 @@ void dialogViewOptions(AppData* app) GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); + nullptr); /* Create the main layout boxes */ GtkWidget* hbox = gtk_hbox_new(FALSE, CELSPACING); @@ -116,12 +214,11 @@ void dialogViewOptions(AppData* app) gtk_container_set_border_width(GTK_CONTAINER(hbox), CELSPACING); float logDistanceLimit = log(app->renderer->getDistanceLimit()) / log((float)MaxDistanceLimit); - GtkAdjustment *adj = (GtkAdjustment *) - gtk_adjustment_new((gfloat)(logDistanceLimit * DistanceSliderRange), - 0.0, DistanceSliderRange, 1.0, 2.0, 0.0); + GtkAdjustment *adj = gtk_adjustment_new(static_cast(logDistanceLimit * DistanceSliderRange), + 0.0, DistanceSliderRange, 1.0, 2.0, 0.0); /* Distance limit slider */ - GtkWidget* magLabel = gtk_label_new(NULL); + GtkWidget* magLabel = gtk_label_new(nullptr); GtkWidget* slider = gtk_hscale_new(adj); g_object_set_data(G_OBJECT(slider), "valueLabel", magLabel); gtk_scale_set_draw_value(GTK_SCALE(slider), 0); @@ -137,13 +234,13 @@ void dialogViewOptions(AppData* app) gtk_range_set_value(GTK_RANGE(textureSlider), app->renderer->getResolution()); gtk_box_pack_start(GTK_BOX(textureBox), textureSlider, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(textureSlider), "value-changed", G_CALLBACK(changeTextureResolution), app); - g_signal_connect(G_OBJECT(textureSlider), "format-value", G_CALLBACK(formatTextureSlider), NULL); + g_signal_connect(G_OBJECT(textureSlider), "format-value", G_CALLBACK(formatTextureSlider), nullptr); - checkButtonsFromAG(actionsRenderFlags, G_N_ELEMENTS(actionsRenderFlags), app->agRender, showBox); - checkButtonsFromAG(actionsOrbitFlags, G_N_ELEMENTS(actionsOrbitFlags), app->agOrbit, orbitBox); - checkButtonsFromAG(actionsLabelFlags, G_N_ELEMENTS(actionsLabelFlags), app->agLabel, labelBox); - toggleButtonsFromAG(actionsVerbosity, G_N_ELEMENTS(actionsVerbosity), app->agVerbosity, infoBox); - toggleButtonsFromAG(actionsAmbientLight, G_N_ELEMENTS(actionsAmbientLight), app->agAmbient, ambientBox); + checkButtonsFromAG(actionsRenderFlags.data(), static_cast(actionsRenderFlags.size()), app->agRender, showBox); + checkButtonsFromAG(actionsOrbitFlags.data(), static_cast(actionsOrbitFlags.size()), app->agOrbit, orbitBox); + checkButtonsFromAG(actionsLabelFlags.data(), static_cast(actionsLabelFlags.size()), app->agLabel, labelBox); + toggleButtonsFromAG(actionsVerbosity.data(), static_cast(actionsVerbosity.size()), app->agVerbosity, infoBox); + toggleButtonsFromAG(actionsAmbientLight.data(), static_cast(actionsAmbientLight.size()), app->agAmbient, ambientBox); g_signal_connect(app->optionDialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), GTK_WIDGET(app->optionDialog)); @@ -156,88 +253,4 @@ void dialogViewOptions(AppData* app) gtk_window_present(GTK_WINDOW(app->optionDialog)); } - -/* CALLBACK: React to changes in the star distance limit slider */ -static gint changeDistanceLimit(GtkRange *slider, AppData* app) -{ - GtkLabel* magLabel = (GtkLabel*)g_object_get_data(G_OBJECT(slider), "valueLabel"); - float limit = makeDistanceLimit(gtk_range_get_value(slider)); - app->renderer->setDistanceLimit(limit); - - char labeltext[16] = "100000 ly"; - sprintf(labeltext, "%ld ly", (long)(limit + 0.5)); - gtk_label_set_text(GTK_LABEL(magLabel), labeltext); - - #ifdef GNOME - /* Distance limit changes do not trigger an event like the other - * render settings. Save setting here. */ - gconf_client_set_int(app->client, "/apps/celestia/distanceLimit", (int)(limit + 0.5), NULL); - #endif /* GNOME */ - - return TRUE; -} - - -/* CALLBACK: React to changes in the texture resolution slider */ -static gint changeTextureResolution(GtkRange *slider, AppData* app) -{ - app->renderer->setResolution((int)gtk_range_get_value(slider)); - - /* Seeing as this is not a GtkAction, kick off the update function */ - resyncTextureResolutionActions(app); - - return TRUE; -} - - -/* CALLBACK: Format the label under the texture detail slider */ -static gchar* formatTextureSlider(GtkRange*, gdouble value) -{ - switch ((int)value) { - case 0: return g_strdup("Low"); - case 1: return g_strdup("Medium"); - case 2: return g_strdup("High"); - default: return g_strdup("Error"); - } -} - - -/* HELPER: Creates check buttons from a GtkActionGroup */ -static void checkButtonsFromAG(const GtkToggleActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box) -{ - for (int i = 0; i < size; i++) { - GtkAction* action = gtk_action_group_get_action(ag, actions[i].name); - - /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label - * is not set with action proxy. */ - GtkWidget* w = gtk_check_button_new_with_mnemonic(actions[i].label); - - gtk_activatable_set_related_action(GTK_ACTIVATABLE(w), action); - gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0); - } -} - - -/* HELPER: Creates toggle (instead of radio) buttons from a GtkActionGroup. - * Cannot be GtkRadioButtons because of GTK limitations/bugs. */ -static void toggleButtonsFromAG(const GtkRadioActionEntry actions[], int size, GtkActionGroup* ag, GtkWidget* box) -{ - for (int i = 0; i < size; i++) { - GtkAction* action = gtk_action_group_get_action(ag, actions[i].name); - - /* Mnemonic work-around for bug in GTK 2.6 > 2.6.2, where the label - * is not set with action proxy. */ - GtkWidget* w = gtk_toggle_button_new_with_mnemonic(actions[i].label); - - gtk_activatable_set_related_action(GTK_ACTIVATABLE(w), action); - gtk_box_pack_start(GTK_BOX(box), w, TRUE, TRUE, 0); - } -} - - -/* HELPER: gives a logarithmic value based on linear value */ -static float makeDistanceLimit(float value) -{ - float logDistanceLimit = value / DistanceSliderRange; - return (float) pow(MaxDistanceLimit, logDistanceLimit); -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-options.h b/src/celestia/gtk/dialog-options.h index 6c92ccac8b..0c1418734c 100644 --- a/src/celestia/gtk/dialog-options.h +++ b/src/celestia/gtk/dialog-options.h @@ -14,23 +14,10 @@ #include "common.h" +namespace celestia::gtk +{ + /* Entry Function */ void dialogViewOptions(AppData* app); - -/* Local data */ -static const char * const ambientLabels[]= -{ - "None", - "Low", - "Medium", - NULL -}; - -static const char * const infoLabels[]= -{ - "None", - "Terse", - "Verbose", - NULL -}; +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-solar.cpp b/src/celestia/gtk/dialog-solar.cpp index f28aec8105..c51f996a0e 100644 --- a/src/celestia/gtk/dialog-solar.cpp +++ b/src/celestia/gtk/dialog-solar.cpp @@ -10,6 +10,9 @@ * $Id: dialog-solar.cpp,v 1.2 2005-12-13 06:19:57 suwalski Exp $ */ +#include +#include + #include #include @@ -23,83 +26,22 @@ #include "actions.h" #include "common.h" - -/* Declarations: Callbacks */ -static void treeSolarSelect(GtkTreeSelection* sel, AppData* app); - -/* Declarations: Helpers */ -static void addPlanetarySystemToTree(const PlanetarySystem* sys, - GtkTreeStore* solarTreeStore, - GtkTreeIter* parent); -static void loadNearestStarSystem(AppData* data, GtkWidget* solarTree, - GtkTreeStore* solarTreeStore); - - -/* ENTRY: Navigation -> Solar System Browser... */ -void dialogSolarBrowser(AppData* app) +namespace celestia::gtk { - GtkWidget *solarTree = NULL; - GtkTreeStore *solarTreeStore = NULL; - - GtkWidget *browser = gtk_dialog_new_with_buttons("Solar System Browser", - GTK_WINDOW(app->mainWindow), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CLOSE, - GTK_RESPONSE_CLOSE, - NULL); - app->simulation->setSelection(Selection((Star *) NULL)); - - /* Solar System Browser */ - GtkWidget *mainbox = gtk_dialog_get_content_area(GTK_DIALOG(browser)); - gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING); - - GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL); - - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_ALWAYS); - gtk_box_pack_start(GTK_BOX(mainbox), scrolled_win, TRUE, TRUE, 0); - - /* Set the tree store to have 2 visible cols, two hidden. The hidden ones - * store pointer to the row's object and its Selection::Type. */ - solarTreeStore = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT); - solarTree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(solarTreeStore)); - - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(solarTree), TRUE); - gtk_container_add(GTK_CONTAINER(scrolled_win), solarTree); - - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - for (int i = 0; i < 2; i++) { - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(ssTitles[i], renderer, "text", i, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(solarTree), column); - gtk_tree_view_column_set_min_width(column, 200); - } - - loadNearestStarSystem(app, solarTree, solarTreeStore); - - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(solarTree)); - g_signal_connect(selection, "changed", G_CALLBACK(treeSolarSelect), app); - - /* Common Buttons */ - GtkWidget *hbox = gtk_hbox_new(TRUE, CELSPACING); - if (buttonMake(hbox, "Center", (GCallback)actionCenterSelection, app)) - return; - if (buttonMake(hbox, "Go To", (GCallback)actionGotoSelection, app)) - return; - gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); - - g_signal_connect(browser, "response", G_CALLBACK(gtk_widget_destroy), browser); - - gtk_widget_set_size_request(browser, -1, 400); /* Absolute Size, urghhh */ - gtk_widget_show_all(browser); -} +namespace +{ +/* Local Data */ +constexpr std::array ssTitles +{ + "Name", + "Type" +}; /* CALLBACK: When Object is selected in Solar System Browser */ -static void treeSolarSelect(GtkTreeSelection* sel, AppData* app) +void +treeSolarSelect(GtkTreeSelection* sel, AppData* app) { gpointer item; SelectionType type; @@ -130,7 +72,8 @@ static void treeSolarSelect(GtkTreeSelection* sel, AppData* app) /* HELPER: Recursively populate GtkTreeView with objects in PlanetarySystem */ -static void addPlanetarySystemToTree(const PlanetarySystem* sys, GtkTreeStore* solarTreeStore, GtkTreeIter* parent) +void +addPlanetarySystemToTree(const PlanetarySystem* sys, GtkTreeStore* solarTreeStore, GtkTreeIter* parent) { const char *name; const char *type; @@ -185,15 +128,15 @@ static void addPlanetarySystemToTree(const PlanetarySystem* sys, GtkTreeStore* s -1); /* Recurse */ - if (satellites != NULL) + if (satellites != nullptr) addPlanetarySystemToTree(satellites, solarTreeStore, &child); } } - /* HELPER: Retrieves closest system and calls addPlanetarySystemToTree to * populate. */ -static void loadNearestStarSystem(AppData* app, GtkWidget* solarTree, GtkTreeStore* solarTreeStore) +void +loadNearestStarSystem(AppData* app, GtkWidget* solarTree, GtkTreeStore* solarTreeStore) { const char* name; char type[30]; @@ -206,15 +149,15 @@ static void loadNearestStarSystem(AppData* app, GtkWidget* solarTree, GtkTreeSto GtkTreeIter top; gtk_tree_store_clear(solarTreeStore); - gtk_tree_store_append(solarTreeStore, &top, NULL); + gtk_tree_store_append(solarTreeStore, &top, nullptr); - if (solarSys != NULL) + if (solarSys != nullptr) { nearestStar = solarSys->getStar(); name = g_strdup(stardb->getStarName(*nearestStar).c_str()); - sprintf(type, "%s Star", nearestStar->getSpectralType()); + std::sprintf(type, "%s Star", nearestStar->getSpectralType()); /* Set up the top-level node. */ gtk_tree_store_set(solarTreeStore, &top, @@ -225,7 +168,7 @@ static void loadNearestStarSystem(AppData* app, GtkWidget* solarTree, GtkTreeSto -1); const PlanetarySystem* planets = solarSys->getPlanets(); - if (planets != NULL) + if (planets != nullptr) addPlanetarySystemToTree(planets, solarTreeStore, &top); /* Open up the top node */ @@ -235,3 +178,71 @@ static void loadNearestStarSystem(AppData* app, GtkWidget* solarTree, GtkTreeSto else gtk_tree_store_set(solarTreeStore, &top, 0, "No Planetary Bodies", -1); } + +} // end unnamed namespace + +/* ENTRY: Navigation -> Solar System Browser... */ +void +dialogSolarBrowser(AppData* app) +{ + GtkWidget *solarTree = nullptr; + GtkTreeStore *solarTreeStore = nullptr; + + GtkWidget *browser = gtk_dialog_new_with_buttons("Solar System Browser", + GTK_WINDOW(app->mainWindow), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE, + nullptr); + app->simulation->setSelection(Selection((Star *) nullptr)); + + /* Solar System Browser */ + GtkWidget *mainbox = gtk_dialog_get_content_area(GTK_DIALOG(browser)); + gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING); + + GtkWidget *scrolled_win = gtk_scrolled_window_new(nullptr, nullptr); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_ALWAYS); + gtk_box_pack_start(GTK_BOX(mainbox), scrolled_win, TRUE, TRUE, 0); + + /* Set the tree store to have 2 visible cols, two hidden. The hidden ones + * store pointer to the row's object and its Selection::Type. */ + solarTreeStore = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT); + solarTree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(solarTreeStore)); + + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(solarTree), TRUE); + gtk_container_add(GTK_CONTAINER(scrolled_win), solarTree); + + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + for (int i = 0; i < 2; i++) + { + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(ssTitles[i], renderer, "text", i, nullptr); + gtk_tree_view_append_column(GTK_TREE_VIEW(solarTree), column); + gtk_tree_view_column_set_min_width(column, 200); + } + + loadNearestStarSystem(app, solarTree, solarTreeStore); + + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(solarTree)); + g_signal_connect(selection, "changed", G_CALLBACK(treeSolarSelect), app); + + /* Common Buttons */ + GtkWidget *hbox = gtk_hbox_new(TRUE, CELSPACING); + if (buttonMake(hbox, "Center", (GCallback)actionCenterSelection, app)) + return; + if (buttonMake(hbox, "Go To", (GCallback)actionGotoSelection, app)) + return; + gtk_box_pack_start(GTK_BOX(mainbox), hbox, FALSE, FALSE, 0); + + g_signal_connect(browser, "response", G_CALLBACK(gtk_widget_destroy), browser); + + gtk_widget_set_size_request(browser, -1, 400); /* Absolute Size, urghhh */ + gtk_widget_show_all(browser); +} + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-solar.h b/src/celestia/gtk/dialog-solar.h index db062c2bf6..8f797bab27 100644 --- a/src/celestia/gtk/dialog-solar.h +++ b/src/celestia/gtk/dialog-solar.h @@ -14,18 +14,12 @@ #include -#include - #include "common.h" +namespace celestia::gtk +{ /* Entry Function */ void dialogSolarBrowser(AppData* app); - -/* Local Data */ -static const char * const ssTitles[] = -{ - "Name", - "Type" -}; +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-star.cpp b/src/celestia/gtk/dialog-star.cpp index 4dcc4ee5f6..7342ec8ad3 100644 --- a/src/celestia/gtk/dialog-star.cpp +++ b/src/celestia/gtk/dialog-star.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -32,8 +33,8 @@ #include "actions.h" #include "common.h" -using namespace std; -namespace engine = celestia::engine; +namespace celestia::gtk +{ namespace { @@ -57,7 +58,8 @@ constexpr std::array sbRadioLabels }; /* Local Data Structures */ -struct sbData { +struct sbData +{ explicit sbData(AppData*); AppData* app; @@ -75,9 +77,9 @@ sbData::sbData(AppData* appData) : { } - /* HELPER: Clear and Add stars to the starListStore */ -static void addStars(sbData* sb) +void +addStars(sbData* sb) { const char *values[5]; GtkTreeIter iter; @@ -103,13 +105,13 @@ static void addStars(sbData* sb) values[0] = g_strdup(ReplaceGreekLetterAbbr((stardb->getStarName(*record.star, true))).c_str()); /* Calculate distance to star */ - sprintf(buf, " %.3f ", record.distance); + std::sprintf(buf, " %.3f ", record.distance); values[1] = g_strdup(buf); - sprintf(buf, " %.2f ", record.appMag); + std::sprintf(buf, " %.2f ", record.appMag); values[2] = g_strdup(buf); - sprintf(buf, " %.2f ", record.star->getAbsoluteMagnitude()); + std::sprintf(buf, " %.2f ", record.star->getAbsoluteMagnitude()); values[3] = g_strdup(buf); gtk_list_store_append(sb->starListStore, &iter); @@ -123,9 +125,9 @@ static void addStars(sbData* sb) } } - /* CALLBACK: When Star is selected in Star Browser */ -static void listStarSelect(GtkTreeSelection* sel, AppData* app) +void +listStarSelect(GtkTreeSelection* sel, AppData* app) { GValue value = { 0, {{0}} }; /* Initialize GValue to 0 */ GtkTreeIter iter; @@ -143,16 +145,16 @@ static void listStarSelect(GtkTreeSelection* sel, AppData* app) app->simulation->setSelection(Selection(const_cast(record->star))); } - /* CALLBACK: Refresh button is pressed. */ -static void refreshBrowser(GtkWidget*, sbData* sb) +void +refreshBrowser(GtkWidget*, sbData* sb) { addStars(sb); } - /* CALLBACK: One of the RadioButtons is pressed */ -static void radioClicked(GtkButton* r, gpointer choice) +void +radioClicked(GtkButton* r, gpointer choice) { sbData* sb = (sbData*)g_object_get_data(G_OBJECT(r), "data"); gint selection = GPOINTER_TO_INT(choice); @@ -179,16 +181,16 @@ static void radioClicked(GtkButton* r, gpointer choice) return; } - refreshBrowser(NULL, sb); + refreshBrowser(nullptr, sb); } - /* CALLBACK: Maximum stars EntryBox changed. */ -static void listStarEntryChange(GtkEntry *entry, GdkEventFocus *event, sbData* sb) +void +listStarEntryChange(GtkEntry *entry, GdkEventFocus *event, sbData* sb) { /* If not called by the slider, but rather by user. Prevents infinite recursion. */ - if (event != NULL) + if (event != nullptr) { std::string_view entryText = gtk_entry_get_text(entry); std::uint32_t numListStars; @@ -198,7 +200,7 @@ static void listStarEntryChange(GtkEntry *entry, GdkEventFocus *event, sbData* s if (!sb->browser.setSize(numListStars)) { /* Call self to set text (NULL event = no recursion) */ - listStarEntryChange(entry, NULL, sb); + listStarEntryChange(entry, nullptr, sb); } gtk_range_set_value(GTK_RANGE(sb->scale), static_cast(numListStars)); @@ -206,31 +208,31 @@ static void listStarEntryChange(GtkEntry *entry, GdkEventFocus *event, sbData* s else { /* Call self to set text (NULL event = no recursion) */ - listStarEntryChange(entry, NULL, sb); + listStarEntryChange(entry, nullptr, sb); } } /* Update value of this box */ char stars[4]; - sprintf(stars, "%" PRIu32, sb->browser.size()); + std::sprintf(stars, "%" PRIu32, sb->browser.size()); gtk_entry_set_text(entry, stars); } - /* CALLBACK: Maximum stars RangeSlider changed. */ -static void listStarSliderChange(GtkRange *range, sbData* sb) +void +listStarSliderChange(GtkRange *range, sbData* sb) { /* Update the value of the text entry box */ sb->browser.setSize(static_cast(gtk_range_get_value(GTK_RANGE(range)))); - listStarEntryChange(GTK_ENTRY(sb->entry), NULL, sb); + listStarEntryChange(GTK_ENTRY(sb->entry), nullptr, sb); /* Refresh the browser listbox */ - refreshBrowser(NULL, sb); + refreshBrowser(nullptr, sb); } - /* CALLBACK: Destroy Window */ -static void starDestroy(GtkWidget* w, gint responseId, sbData* sb) +void +starDestroy(GtkWidget* w, gint responseId, sbData* sb) { gtk_widget_destroy(GTK_WIDGET(w)); @@ -238,12 +240,11 @@ static void starDestroy(GtkWidget* w, gint responseId, sbData* sb) delete sb; } - } // end unnamed namespace - /* ENTRY: Navigation -> Star Browser... */ -void dialogStarBrowser(AppData* app) +void +dialogStarBrowser(AppData* app) { auto sb = new sbData(app); @@ -251,14 +252,14 @@ void dialogStarBrowser(AppData* app) GTK_WINDOW(app->mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, - NULL); + nullptr); app->simulation->setSelection(Selection()); /* Star System Browser */ GtkWidget *mainbox = gtk_dialog_get_content_area(GTK_DIALOG(browser)); gtk_container_set_border_width(GTK_CONTAINER(mainbox), CELSPACING); - GtkWidget *scrolled_win = gtk_scrolled_window_new (NULL, NULL); + GtkWidget *scrolled_win = gtk_scrolled_window_new (nullptr, nullptr); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, @@ -284,11 +285,11 @@ void dialogStarBrowser(AppData* app) /* Add the columns */ for (int i=0; i<5; i++) { renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes (sbTitles[i], renderer, "text", i, NULL); + column = gtk_tree_view_column_new_with_attributes (sbTitles[i], renderer, "text", i, nullptr); if (i > 0 && i < 4) { /* Right align */ gtk_tree_view_column_set_alignment(column, 1.0); - g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); + g_object_set(G_OBJECT(renderer), "xalign", 1.0, nullptr); } gtk_tree_view_append_column(GTK_TREE_VIEW(starList), column); } @@ -327,13 +328,13 @@ void dialogStarBrowser(AppData* app) if (sb->browser.size() == engine::StarBrowser::MinListStars) { /* Force update manually (scale won't trigger event) */ - listStarEntryChange(GTK_ENTRY(sb->entry), NULL, sb); - refreshBrowser(NULL, sb); + listStarEntryChange(GTK_ENTRY(sb->entry), nullptr, sb); + refreshBrowser(nullptr, sb); } /* Radio Buttons */ vbox = gtk_vbox_new(TRUE, 0); - makeRadioItems(sbRadioLabels.data(), vbox, G_CALLBACK(radioClicked), NULL, sb); + makeRadioItems(sbRadioLabels.data(), vbox, G_CALLBACK(radioClicked), nullptr, sb); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); /* Common Buttons */ @@ -351,3 +352,5 @@ void dialogStarBrowser(AppData* app) gtk_widget_set_size_request(browser, -1, 400); /* Absolute Size, urghhh */ gtk_widget_show_all(browser); } + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-star.h b/src/celestia/gtk/dialog-star.h index 32c1f2f32c..e0f7429b73 100644 --- a/src/celestia/gtk/dialog-star.h +++ b/src/celestia/gtk/dialog-star.h @@ -16,5 +16,10 @@ #include "common.h" +namespace celestia::gtk +{ + /* Entry Function */ void dialogStarBrowser(AppData* app); + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-time.cpp b/src/celestia/gtk/dialog-time.cpp index 0d6a8020a1..2c7a3f58d5 100644 --- a/src/celestia/gtk/dialog-time.cpp +++ b/src/celestia/gtk/dialog-time.cpp @@ -10,8 +10,10 @@ * $Id: dialog-time.cpp,v 1.3 2005-12-13 03:54:40 suwalski Exp $ */ +#include +#include + #include -#include #include #include @@ -19,22 +21,107 @@ #include "dialog-time.h" #include "common.h" -namespace astro = celestia::astro; +namespace celestia::gtk +{ + +namespace +{ /* Labels for TimeZone dropdown */ -static const char* timeOptions[] = { "UTC", "Local", NULL }; +constexpr std::array timeOptions{ "UTC", "Local", static_cast(nullptr) }; + +/* CALLBACK: spinner value changed */ +gboolean +intAdjChanged(GtkAdjustment* adj, int *val) +{ + if (val) + { + *val = (int)gtk_adjustment_get_value(adj); + return TRUE; + } + return FALSE; +} + +/* CALLBACK: time zone selected from drop-down */ +gboolean +zoneChosen(GtkComboBox *menu, gboolean* timezone) +{ + *timezone = gtk_combo_box_get_active(menu) + 1; + return TRUE; +} + +/* CALLBACK: month selected from drop-down */ +gboolean +monthChosen(GtkComboBox *menu, int* month) +{ + if (month) + *month = gtk_combo_box_get_active(menu) + 1; + return TRUE; +} + +/* HELPER: creates one of the several drop-down boxes */ +void +chooseOption(GtkWidget *hbox, const char *str, char *choices[], int *val, GCallback chosen) +{ + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + GtkWidget *label = gtk_label_new(str); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + GtkWidget* combo = gtk_combo_box_text_new(); + + for(unsigned int i = 0; choices[i]; i++) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), choices[i]); + } + + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 7); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 2); + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), (*val - 1)); + + g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(chosen), (gpointer)val); +} + +/* HELPER: creates spinner */ +void +intSpin(GtkWidget *hbox, const char *str, int min, int max, int *val, const char *sep) +{ + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + GtkWidget *label = gtk_label_new(str); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new ((float)*val, (float) min, (float) max, + 1.0, 5.0, 0.0); + GtkWidget *spinner = gtk_spin_button_new (adj, 1.0, 0); + gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (spinner), TRUE); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); + gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON (spinner),TRUE); + gtk_entry_set_max_length(GTK_ENTRY (spinner), ((max<99)?2:4) ); + + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); -/* Declarations: Callbacks */ -static gboolean intAdjChanged(GtkAdjustment* adj, int *val); -static gboolean zoneChosen(GtkComboBox *menu, int* timezone); -static gboolean monthChosen(GtkComboBox *menu, int* month); + if ((sep) && (*sep)) + { + gtk_widget_show (label); + GtkWidget *hbox2 = gtk_hbox_new(FALSE, 3); + label = gtk_label_new(sep); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_box_pack_start (GTK_BOX (hbox2), spinner, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 7); + gtk_widget_show (label); + gtk_widget_show (hbox2); + } + else + { + gtk_box_pack_start (GTK_BOX (vbox), spinner, TRUE, TRUE, 7); + } -/* Declarations: Helpers */ -static void chooseOption(GtkWidget *hbox, const char *str, char *choices[], - int *val, GCallback chosen); -static void intSpin(GtkWidget *hbox, const char *str, int min, int max, - int *val, const char *sep); + g_signal_connect(G_OBJECT(adj), "value-changed", + G_CALLBACK(intAdjChanged), val); +} +} // end unnamed namespace /* ENTRY: Dialog initializer */ void dialogSetTime(AppData* app) @@ -50,7 +137,7 @@ void dialogSetTime(AppData* app) GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - NULL); + nullptr); if (app->showLocalTime) timezone = 2; @@ -77,7 +164,7 @@ void dialogSetTime(AppData* app) chooseOption(hbox, "Timezone", - (char **)timeOptions, + const_cast(timeOptions.data()), &timezone, G_CALLBACK(zoneChosen)); @@ -89,7 +176,7 @@ void dialogSetTime(AppData* app) chooseOption(hbox, "Month", - (char **)monthOptions, + const_cast(monthOptions.data()), &date.month, G_CALLBACK(monthChosen)); @@ -112,7 +199,7 @@ void dialogSetTime(AppData* app) if (button == GTK_RESPONSE_ACCEPT) /* Set current time and exit. */ - app->simulation->setTime((double)time(NULL) / 86400.0 + (double)astro::Date(1970, 1, 1)); + app->simulation->setTime((double)std::time(nullptr) / 86400.0 + (double)astro::Date(1970, 1, 1)); else if (button == GTK_RESPONSE_OK) /* Set entered time and exit */ app->simulation->setTime((double)date - ((timezone == 1) ? 0 : astro::secondsToJulianDate(tzOffsetAtDate(date)))); @@ -120,93 +207,4 @@ void dialogSetTime(AppData* app) gtk_widget_destroy(stimedialog); } - -/* CALLBACK: spinner value changed */ -static gboolean intAdjChanged(GtkAdjustment* adj, int *val) -{ - if (val) - { - *val = (int)gtk_adjustment_get_value(adj); - return TRUE; - } - return FALSE; -} - - -/* CALLBACK: time zone selected from drop-down */ -static gboolean zoneChosen(GtkComboBox *menu, gboolean* timezone) -{ - *timezone = gtk_combo_box_get_active(menu) + 1; - return TRUE; -} - - -/* CALLBACK: month selected from drop-down */ -static gboolean monthChosen(GtkComboBox *menu, int* month) -{ - if (month) - *month = gtk_combo_box_get_active(menu) + 1; - return TRUE; -} - - -/* HELPER: creates one of the several drop-down boxes */ -static void chooseOption(GtkWidget *hbox, const char *str, char *choices[], int *val, GCallback chosen) -{ - GtkWidget *vbox = gtk_vbox_new(FALSE, 0); - GtkWidget *label = gtk_label_new(str); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - GtkWidget* combo = gtk_combo_box_text_new(); - - for(unsigned int i = 0; choices[i]; i++) - { - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), choices[i]); - } - - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 7); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 2); - - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), (*val - 1)); - - g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(chosen), (gpointer)val); -} - - -/* HELPER: creates spinner */ -static void intSpin(GtkWidget *hbox, const char *str, int min, int max, int *val, const char *sep) -{ - GtkWidget *vbox = gtk_vbox_new(FALSE, 0); - GtkWidget *label = gtk_label_new(str); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new ((float)*val, (float) min, (float) max, - 1.0, 5.0, 0.0); - GtkWidget *spinner = gtk_spin_button_new (adj, 1.0, 0); - gtk_spin_button_set_numeric(GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE); - gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON (spinner),TRUE); - gtk_entry_set_max_length(GTK_ENTRY (spinner), ((max<99)?2:4) ); - - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - if ((sep) && (*sep)) - { - gtk_widget_show (label); - GtkWidget *hbox2 = gtk_hbox_new(FALSE, 3); - label = gtk_label_new(sep); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_box_pack_start (GTK_BOX (hbox2), spinner, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 7); - gtk_widget_show (label); - gtk_widget_show (hbox2); - } - else - { - gtk_box_pack_start (GTK_BOX (vbox), spinner, TRUE, TRUE, 7); - } - - g_signal_connect(G_OBJECT(adj), "value-changed", - G_CALLBACK(intAdjChanged), val); -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-time.h b/src/celestia/gtk/dialog-time.h index c05adb1051..488810b4c8 100644 --- a/src/celestia/gtk/dialog-time.h +++ b/src/celestia/gtk/dialog-time.h @@ -16,6 +16,10 @@ #include "common.h" +namespace celestia::gtk +{ /* Entry Function */ void dialogSetTime(AppData* app); + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-tour.cpp b/src/celestia/gtk/dialog-tour.cpp index 69ecfe4185..8cba6543f8 100644 --- a/src/celestia/gtk/dialog-tour.cpp +++ b/src/celestia/gtk/dialog-tour.cpp @@ -10,6 +10,8 @@ * $Id: dialog-tour.cpp,v 1.1 2005-12-06 03:19:35 suwalski Exp $ */ +#include + #include #include @@ -18,18 +20,88 @@ #include "dialog-tour.h" #include "common.h" -using namespace Eigen; +namespace celestia::gtk +{ + +namespace +{ + +/* Local Data Struct */ +typedef struct _TourData TourData; +struct _TourData { + AppData* app; + + Destination* selected; + GtkWidget* descLabel; +}; + +/* CALLBACK: tour list object selected */ +gint +TourGuideSelect(GtkComboBox* comboBox, TourData* td) +{ + int itemIndex = gtk_combo_box_get_active(comboBox); + + const DestinationList* destinations = td->app->core->getDestinations(); + if (destinations != nullptr && + itemIndex >= 0 && itemIndex < (int) destinations->size()) + { + td->selected = (*destinations)[itemIndex]; + } + + if (td->descLabel != nullptr && td->selected != nullptr) + { + gtk_label_set_text(GTK_LABEL(td->descLabel), td->selected->description.c_str()); + } + + return TRUE; +} + +/* CALLBACK: Goto button clicked */ +gint +TourGuideGoto(GtkWidget*, TourData* td) +{ + Simulation* simulation = td->app->simulation; + if (td->selected != nullptr && simulation != nullptr) + { + Selection sel = simulation->findObjectFromPath(td->selected->target); + if (!sel.empty()) + { + simulation->follow(); + simulation->setSelection(sel); + if (td->selected->distance <= 0) + { + /* Use the default distance */ + simulation->gotoSelection(5.0, + Eigen::Vector3f::UnitY(), + ObserverFrame::ObserverLocal); + } + else + { + simulation->gotoSelection(5.0, + td->selected->distance, + Eigen::Vector3f::UnitY(), + ObserverFrame::ObserverLocal); + } + } + } + return TRUE; +} -/* Declarations: Callbacks */ -static gint TourGuideSelect(GtkComboBox* comboBox, TourData* td); -static gint TourGuideGoto(GtkWidget*, TourData* td); -static void TourGuideDestroy(GtkWidget* w, gint, TourData* td); +/* CALLBACK: Destroy Window */ +void +TourGuideDestroy(GtkWidget* w, gint, TourData* td) +{ + gtk_widget_destroy(GTK_WIDGET(w)); + g_free(td); +} +} // end unnamed namespace /* ENTRY: Navigation->Tour Guide... */ -void dialogTourGuide(AppData* app) +void +dialogTourGuide(AppData* app) { TourData* td = g_new0(TourData, 1); td->app = app; @@ -39,7 +111,7 @@ void dialogTourGuide(AppData* app) GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - NULL); + nullptr); GtkWidget* hbox = gtk_hbox_new(FALSE, CELSPACING); gtk_container_set_border_width(GTK_CONTAINER(hbox), CELSPACING); @@ -66,13 +138,11 @@ void dialogTourGuide(AppData* app) const DestinationList* destinations = app->core->getDestinations(); int index = -1; - if (destinations != NULL) + if (destinations != nullptr) { - for (DestinationList::const_iterator iter = destinations->begin(); - iter != destinations->end(); iter++) + for (const Destination* dest : *destinations) { - Destination* dest = *iter; - if (dest != NULL) + if (dest != nullptr) { index = 0; gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(comboBox), dest->name.c_str()); @@ -100,64 +170,4 @@ void dialogTourGuide(AppData* app) gtk_widget_show_all(dialog); } - -/* CALLBACK: tour list object selected */ -static gint TourGuideSelect(GtkComboBox* comboBox, TourData* td) -{ - int itemIndex = gtk_combo_box_get_active(comboBox); - - const DestinationList* destinations = td->app->core->getDestinations(); - if (destinations != NULL && - itemIndex >= 0 && itemIndex < (int) destinations->size()) - { - td->selected = (*destinations)[itemIndex]; - } - - if (td->descLabel != NULL && td->selected != NULL) - { - gtk_label_set_text(GTK_LABEL(td->descLabel), td->selected->description.c_str()); - } - - return TRUE; -} - - -/* CALLBACK: Goto button clicked */ -static gint TourGuideGoto(GtkWidget*, TourData* td) -{ - Simulation* simulation = td->app->simulation; - - if (td->selected != NULL && simulation != NULL) - { - Selection sel = simulation->findObjectFromPath(td->selected->target); - if (!sel.empty()) - { - simulation->follow(); - simulation->setSelection(sel); - if (td->selected->distance <= 0) - { - /* Use the default distance */ - simulation->gotoSelection(5.0, - Vector3f::UnitY(), - ObserverFrame::ObserverLocal); - } - else - { - simulation->gotoSelection(5.0, - td->selected->distance, - Vector3f::UnitY(), - ObserverFrame::ObserverLocal); - } - } - } - - return TRUE; -} - - -/* CALLBACK: Destroy Window */ -static void TourGuideDestroy(GtkWidget* w, gint, TourData* td) -{ - gtk_widget_destroy(GTK_WIDGET(w)); - g_free(td); -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/dialog-tour.h b/src/celestia/gtk/dialog-tour.h index 24b865c2d1..c5f1c0c256 100644 --- a/src/celestia/gtk/dialog-tour.h +++ b/src/celestia/gtk/dialog-tour.h @@ -16,16 +16,10 @@ #include "common.h" +namespace celestia::gtk +{ /* Entry Function */ void dialogTourGuide(AppData* app); - -/* Local Data Struct */ -typedef struct _TourData TourData; -struct _TourData { - AppData* app; - - Destination* selected; - GtkWidget* descLabel; -}; +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/glwidget.cpp b/src/celestia/gtk/glwidget.cpp index 02277af75d..23b45d45fc 100644 --- a/src/celestia/gtk/glwidget.cpp +++ b/src/celestia/gtk/glwidget.cpp @@ -24,68 +24,179 @@ #include "actions.h" #include "common.h" +namespace celestia::gtk +{ -/* Declarations: Callbacks */ -static gint glarea_idle(AppData* app); -static gint glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app); -#if GTK_MAJOR_VERSION == 2 -static gint glarea_expose(GtkWidget* widget, GdkEventExpose* event, AppData* app); +namespace +{ + +/* HELPER: GL Common Draw function. + * If everything checks out, call appCore->draw() */ +gint +glDrawFrame(AppData* app) +{ +#ifdef GTKGLEXT + GdkGLContext *glcontext = gtk_widget_get_gl_context(app->glArea); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(app->glArea); + + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + return FALSE; #else -static gint glarea_draw(GtkWidget*, cairo_t*, AppData* app); + if (!gtk_egl_drawable_make_current(app->glArea)) + return FALSE; #endif -static gint glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app); -static gint glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app); -static gint glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app); -static gint glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* app); -static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app); -static gint glarea_key_release(GtkWidget* widget, GdkEventKey* event, AppData* app); -/* Declarations: Helpers */ -static gint glDrawFrame(AppData* app); -static bool handleSpecialKey(int key, int state, bool down, AppData* app); + if (app->bReady) + { + app->core->draw(); +#ifdef GTKGLEXT + gdk_gl_drawable_swap_buffers(GDK_GL_DRAWABLE(gldrawable)); +#else + gtk_egl_drawable_swap_buffers(app->glArea); +#endif + } +#ifdef GTKGLEXT + gdk_gl_drawable_gl_end(gldrawable); +#endif + return TRUE; +} -/* ENTRY: Initialize/Bind all glArea Callbacks */ -void initGLCallbacks(AppData* app) +/* HELPER: Lookup function for keypress-action. Any key that is not part of + * the menu system must be listed here. */ +bool +handleSpecialKey(int key, int state, bool down, AppData* app) { -#if GTK_MAJOR_VERSION == 2 - g_signal_connect(G_OBJECT(app->glArea), "expose_event", - G_CALLBACK(glarea_expose), app); -#else - g_signal_connect(G_OBJECT(app->glArea), "draw", - G_CALLBACK(glarea_draw), app); -#endif - g_signal_connect(G_OBJECT(app->glArea), "configure_event", - G_CALLBACK(glarea_configure), app); - g_signal_connect(G_OBJECT(app->glArea), "button_press_event", - G_CALLBACK(glarea_button_press), app); - g_signal_connect(G_OBJECT(app->glArea), "button_release_event", - G_CALLBACK(glarea_button_release), app); - g_signal_connect(G_OBJECT(app->glArea), "scroll_event", - G_CALLBACK(glarea_mouse_scroll), app); - g_signal_connect(G_OBJECT(app->glArea), "motion_notify_event", - G_CALLBACK(glarea_motion_notify), app); - g_signal_connect(G_OBJECT(app->glArea), "key_press_event", - G_CALLBACK(glarea_key_press), app); - g_signal_connect(G_OBJECT(app->glArea), "key_release_event", - G_CALLBACK(glarea_key_release), app); + int k = -1; - /* Main call to execute redraw during GTK main loop */ - g_idle_add((GSourceFunc)glarea_idle, app); + switch (key) + { + case GDK_KEY_Up: + k = CelestiaCore::Key_Up; + break; + case GDK_KEY_Down: + k = CelestiaCore::Key_Down; + break; + case GDK_KEY_Left: + k = CelestiaCore::Key_Left; + break; + case GDK_KEY_Right: + k = CelestiaCore::Key_Right; + break; + case GDK_KEY_Home: + k = CelestiaCore::Key_Home; + break; + case GDK_KEY_End: + k = CelestiaCore::Key_End; + break; + case GDK_KEY_F1: + k = CelestiaCore::Key_F1; + break; + case GDK_KEY_F2: + k = CelestiaCore::Key_F2; + break; + case GDK_KEY_F3: + k = CelestiaCore::Key_F3; + break; + case GDK_KEY_F4: + k = CelestiaCore::Key_F4; + break; + case GDK_KEY_F5: + k = CelestiaCore::Key_F5; + break; + case GDK_KEY_F6: + k = CelestiaCore::Key_F6; + break; + case GDK_KEY_F7: + k = CelestiaCore::Key_F7; + break; + case GDK_KEY_F10: + if (down) + actionCaptureImage(nullptr, app); + break; + case GDK_KEY_F11: + k = CelestiaCore::Key_F11; + break; + case GDK_KEY_F12: + k = CelestiaCore::Key_F12; + break; + case GDK_KEY_KP_Insert: + case GDK_KEY_KP_0: + k = CelestiaCore::Key_NumPad0; + break; + case GDK_KEY_KP_End: + case GDK_KEY_KP_1: + k = CelestiaCore::Key_NumPad1; + break; + case GDK_KEY_KP_Down: + case GDK_KEY_KP_2: + k = CelestiaCore::Key_NumPad2; + break; + case GDK_KEY_KP_Next: + case GDK_KEY_KP_3: + k = CelestiaCore::Key_NumPad3; + break; + case GDK_KEY_KP_Left: + case GDK_KEY_KP_4: + k = CelestiaCore::Key_NumPad4; + break; + case GDK_KEY_KP_Begin: + case GDK_KEY_KP_5: + k = CelestiaCore::Key_NumPad5; + break; + case GDK_KEY_KP_Right: + case GDK_KEY_KP_6: + k = CelestiaCore::Key_NumPad6; + break; + case GDK_KEY_KP_Home: + case GDK_KEY_KP_7: + k = CelestiaCore::Key_NumPad7; + break; + case GDK_KEY_KP_Up: + case GDK_KEY_KP_8: + k = CelestiaCore::Key_NumPad8; + break; + case GDK_KEY_KP_Prior: + case GDK_KEY_KP_9: + k = CelestiaCore::Key_NumPad9; + break; + case GDK_KEY_A: + case GDK_KEY_a: + k = 'A'; + break; + case GDK_KEY_Z: + case GDK_KEY_z: + k = 'Z'; + break; + } + if (k >= 0) + { + if (down) + app->core->keyDown(k, (state & GDK_SHIFT_MASK) + ? CelestiaCore::ShiftKey + : 0); + else + app->core->keyUp(k); + return (k < 'A' || k > 'Z'); + } + else + { + return false; + } } - /* CALLBACK: GL Function for main update (in GTK idle loop) */ -static gint glarea_idle(AppData* app) +gint +glarea_idle(AppData* app) { app->core->tick(); return glDrawFrame(app); } - /* CALLBACK: GL Function for event "configure_event" */ -static gint glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app) +gint +glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app) { #ifdef GTKGLEXT GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); @@ -110,10 +221,10 @@ static gint glarea_configure(GtkWidget* widget, GdkEventConfigure*, AppData* app return TRUE; } - #if GTK_MAJOR_VERSION == 2 /* CALLBACK: GL Function for event "expose_event" */ -static gint glarea_expose(GtkWidget*, GdkEventExpose* event, AppData* app) +gint +glarea_expose(GtkWidget*, GdkEventExpose* event, AppData* app) { /* Draw only the last expose */ if (event->count > 0) @@ -124,15 +235,16 @@ static gint glarea_expose(GtkWidget*, GdkEventExpose* event, AppData* app) } #else /* CALLBACK: GL Function for event "draw" */ -static gint glarea_draw(GtkWidget*, cairo_t*, AppData* app) +gint +glarea_draw(GtkWidget*, cairo_t*, AppData* app) { return glDrawFrame(app); } #endif - /* CALLBACK: GL Function for event "motion_notify_event" */ -static gint glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app) +gint +glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app) { int x = (int) event->x; int y = (int) event->y; @@ -157,9 +269,9 @@ static gint glarea_motion_notify(GtkWidget*, GdkEventMotion* event, AppData* app return TRUE; } - /* CALLBACK: GL Function for event "scroll_event" */ -static gint glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app) +gint +glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app) { if (event->direction == GDK_SCROLL_UP) app->core->mouseWheel(-1.0f, 0); @@ -169,9 +281,9 @@ static gint glarea_mouse_scroll(GtkWidget*, GdkEventScroll* event, AppData* app) return TRUE; } - /* CALLBACK: GL Function for event "button_press_event" */ -static gint glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app) +gint +glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app) { app->lastX = (int) event->x; app->lastY = (int) event->y; @@ -186,9 +298,9 @@ static gint glarea_button_press(GtkWidget*, GdkEventButton* event, AppData* app) return TRUE; } - /* CALLBACK: GL Function for event "button_release_event" */ -static gint glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* app) +gint +glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* app) { app->lastX = (int) event->x; app->lastY = (int) event->y; @@ -203,9 +315,9 @@ static gint glarea_button_release(GtkWidget*, GdkEventButton* event, AppData* ap return TRUE; } - /* CALLBACK: GL Function for event "key_press_event" */ -static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app) +gint +glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app) { switch (event->keyval) { @@ -234,7 +346,7 @@ static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app default: if (!handleSpecialKey(event->keyval, event->state, true, app)) { - if ((event->string != NULL) && (*(event->string))) + if ((event->string != nullptr) && (*(event->string))) { /* See if our key accelerators will handle this event. */ if (app->core->getTextEnterMode() != celestia::Hud::TextEnterMode::Normal && @@ -259,164 +371,42 @@ static gint glarea_key_press(GtkWidget* widget, GdkEventKey* event, AppData* app return TRUE; } - /* CALLBACK: GL Function for event "key_release_event" */ -static gint glarea_key_release(GtkWidget* widget, GdkEventKey* event, AppData* app) +gint +glarea_key_release(GtkWidget* widget, GdkEventKey* event, AppData* app) { return handleSpecialKey(event->keyval, event->state, false, app); } +} // end unnamed namespace -/* HELPER: GL Common Draw function. - * If everything checks out, call appCore->draw() */ -static gint glDrawFrame(AppData* app) +/* ENTRY: Initialize/Bind all glArea Callbacks */ +void initGLCallbacks(AppData* app) { -#ifdef GTKGLEXT - GdkGLContext *glcontext = gtk_widget_get_gl_context(app->glArea); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(app->glArea); - - if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) - return FALSE; -#else - if (!gtk_egl_drawable_make_current(app->glArea)) - return FALSE; -#endif - - if (app->bReady) - { - app->core->draw(); -#ifdef GTKGLEXT - gdk_gl_drawable_swap_buffers(GDK_GL_DRAWABLE(gldrawable)); +#if GTK_MAJOR_VERSION == 2 + g_signal_connect(G_OBJECT(app->glArea), "expose_event", + G_CALLBACK(glarea_expose), app); #else - gtk_egl_drawable_swap_buffers(app->glArea); + g_signal_connect(G_OBJECT(app->glArea), "draw", + G_CALLBACK(glarea_draw), app); #endif - } + g_signal_connect(G_OBJECT(app->glArea), "configure_event", + G_CALLBACK(glarea_configure), app); + g_signal_connect(G_OBJECT(app->glArea), "button_press_event", + G_CALLBACK(glarea_button_press), app); + g_signal_connect(G_OBJECT(app->glArea), "button_release_event", + G_CALLBACK(glarea_button_release), app); + g_signal_connect(G_OBJECT(app->glArea), "scroll_event", + G_CALLBACK(glarea_mouse_scroll), app); + g_signal_connect(G_OBJECT(app->glArea), "motion_notify_event", + G_CALLBACK(glarea_motion_notify), app); + g_signal_connect(G_OBJECT(app->glArea), "key_press_event", + G_CALLBACK(glarea_key_press), app); + g_signal_connect(G_OBJECT(app->glArea), "key_release_event", + G_CALLBACK(glarea_key_release), app); -#ifdef GTKGLEXT - gdk_gl_drawable_gl_end(gldrawable); -#endif - return TRUE; + /* Main call to execute redraw during GTK main loop */ + g_idle_add((GSourceFunc)glarea_idle, app); } - -/* HELPER: Lookup function for keypress-action. Any key that is not part of - * the menu system must be listed here. */ -static bool handleSpecialKey(int key, int state, bool down, AppData* app) -{ - int k = -1; - - switch (key) - { - case GDK_KEY_Up: - k = CelestiaCore::Key_Up; - break; - case GDK_KEY_Down: - k = CelestiaCore::Key_Down; - break; - case GDK_KEY_Left: - k = CelestiaCore::Key_Left; - break; - case GDK_KEY_Right: - k = CelestiaCore::Key_Right; - break; - case GDK_KEY_Home: - k = CelestiaCore::Key_Home; - break; - case GDK_KEY_End: - k = CelestiaCore::Key_End; - break; - case GDK_KEY_F1: - k = CelestiaCore::Key_F1; - break; - case GDK_KEY_F2: - k = CelestiaCore::Key_F2; - break; - case GDK_KEY_F3: - k = CelestiaCore::Key_F3; - break; - case GDK_KEY_F4: - k = CelestiaCore::Key_F4; - break; - case GDK_KEY_F5: - k = CelestiaCore::Key_F5; - break; - case GDK_KEY_F6: - k = CelestiaCore::Key_F6; - break; - case GDK_KEY_F7: - k = CelestiaCore::Key_F7; - break; - case GDK_KEY_F10: - if (down) actionCaptureImage(NULL, app); - break; - case GDK_KEY_F11: - k = CelestiaCore::Key_F11; - break; - case GDK_KEY_F12: - k = CelestiaCore::Key_F12; - break; - case GDK_KEY_KP_Insert: - case GDK_KEY_KP_0: - k = CelestiaCore::Key_NumPad0; - break; - case GDK_KEY_KP_End: - case GDK_KEY_KP_1: - k = CelestiaCore::Key_NumPad1; - break; - case GDK_KEY_KP_Down: - case GDK_KEY_KP_2: - k = CelestiaCore::Key_NumPad2; - break; - case GDK_KEY_KP_Next: - case GDK_KEY_KP_3: - k = CelestiaCore::Key_NumPad3; - break; - case GDK_KEY_KP_Left: - case GDK_KEY_KP_4: - k = CelestiaCore::Key_NumPad4; - break; - case GDK_KEY_KP_Begin: - case GDK_KEY_KP_5: - k = CelestiaCore::Key_NumPad5; - break; - case GDK_KEY_KP_Right: - case GDK_KEY_KP_6: - k = CelestiaCore::Key_NumPad6; - break; - case GDK_KEY_KP_Home: - case GDK_KEY_KP_7: - k = CelestiaCore::Key_NumPad7; - break; - case GDK_KEY_KP_Up: - case GDK_KEY_KP_8: - k = CelestiaCore::Key_NumPad8; - break; - case GDK_KEY_KP_Prior: - case GDK_KEY_KP_9: - k = CelestiaCore::Key_NumPad9; - break; - case GDK_KEY_A: - case GDK_KEY_a: - k = 'A'; - break; - case GDK_KEY_Z: - case GDK_KEY_z: - k = 'Z'; - break; - } - - if (k >= 0) - { - if (down) - app->core->keyDown(k, (state & GDK_SHIFT_MASK) - ? CelestiaCore::ShiftKey - : 0); - else - app->core->keyUp(k); - return (k < 'A' || k > 'Z'); - } - else - { - return false; - } -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/glwidget.h b/src/celestia/gtk/glwidget.h index 77d078a040..a7dbf1626b 100644 --- a/src/celestia/gtk/glwidget.h +++ b/src/celestia/gtk/glwidget.h @@ -17,6 +17,10 @@ #include "common.h" +namespace celestia::gtk +{ /* Initialization Functions */ void initGLCallbacks(AppData* app); + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/main.cpp b/src/celestia/gtk/main.cpp index 1346ffceef..4f09457678 100644 --- a/src/celestia/gtk/main.cpp +++ b/src/celestia/gtk/main.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -38,13 +39,6 @@ #include #include -/* Includes for the GNOME front-end */ -#ifdef GNOME -#include -#include -#include -#endif /* GNOME */ - /* Includes for the GTK front-end */ #include "common.h" #include "glwidget.h" @@ -53,47 +47,43 @@ #include "ui.h" /* Includes for the settings interface */ -#ifdef GNOME -#include "settings-gconf.h" -#else #include "settings-file.h" -#endif /* GNOME */ #ifndef DEBUG #define G_DISABLE_ASSERT #endif /* DEBUG */ +namespace celestia::gtk +{ -using namespace celestia; -using namespace std; - +namespace +{ /* Function Definitions */ -static void createMainMenu(GtkWidget* window, AppData* app); -static void initRealize(GtkWidget* widget, AppData* app); - +void createMainMenu(GtkWidget* window, AppData* app); +void initRealize(GtkWidget* widget, AppData* app); /* Command-Line Options */ -static gchar* configFile = NULL; -static gchar* installDir = NULL; -static gchar** extrasDir = NULL; -static gboolean fullScreen = FALSE; -static gboolean noSplash = FALSE; +gchar* configFile = nullptr; +gchar* installDir = nullptr; +gchar** extrasDir = nullptr; +gboolean fullScreen = FALSE; +gboolean noSplash = FALSE; /* Command-Line Options specification */ -static GOptionEntry optionEntries[] = +constexpr std::array optionEntries { - { "conf", 'c', 0, G_OPTION_ARG_FILENAME, &configFile, "Alternate configuration file", "file" }, - { "dir", 'd', 0, G_OPTION_ARG_FILENAME, &installDir, "Alternate installation directory", "directory" }, - { "extrasdir", 'e', 0, G_OPTION_ARG_FILENAME_ARRAY, &extrasDir, "Additional \"extras\" directory", "directory" }, - { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullScreen, "Start full-screen", NULL }, - { "nosplash", 's', 0, G_OPTION_ARG_NONE, &noSplash, "Disable splash screen", NULL }, - { NULL, '\0', 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + GOptionEntry{ "conf", 'c', 0, G_OPTION_ARG_FILENAME, &configFile, "Alternate configuration file", "file" }, + GOptionEntry{ "dir", 'd', 0, G_OPTION_ARG_FILENAME, &installDir, "Alternate installation directory", "directory" }, + GOptionEntry{ "extrasdir", 'e', 0, G_OPTION_ARG_FILENAME_ARRAY, &extrasDir, "Additional \"extras\" directory", "directory" }, + GOptionEntry{ "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullScreen, "Start full-screen", nullptr }, + GOptionEntry{ "nosplash", 's', 0, G_OPTION_ARG_NONE, &noSplash, "Disable splash screen", nullptr }, + GOptionEntry{ nullptr, '\0', 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } }; - /* Initializes GtkActions and creates main menu */ -static void createMainMenu(GtkWidget* window, AppData* app) +void +createMainMenu(GtkWidget* window, AppData* app) { GtkUIManager *ui_manager; GtkAccelGroup *accel_group; @@ -108,14 +98,14 @@ static void createMainMenu(GtkWidget* window, AppData* app) app->agAmbient = gtk_action_group_new("AmbientActions"); /* All actions have the AppData structure passed */ - gtk_action_group_add_actions(app->agMain, actionsPlain, G_N_ELEMENTS(actionsPlain), app); - gtk_action_group_add_toggle_actions(app->agMain, actionsToggle, G_N_ELEMENTS(actionsToggle), app); - gtk_action_group_add_radio_actions(app->agVerbosity, actionsVerbosity, G_N_ELEMENTS(actionsVerbosity), 0, G_CALLBACK(actionVerbosity), app); - gtk_action_group_add_radio_actions(app->agStarStyle, actionsStarStyle, G_N_ELEMENTS(actionsStarStyle), 0, G_CALLBACK(actionStarStyle), app); - gtk_action_group_add_radio_actions(app->agAmbient, actionsAmbientLight, G_N_ELEMENTS(actionsAmbientLight), 0, G_CALLBACK(actionAmbientLight), app); - gtk_action_group_add_toggle_actions(app->agRender, actionsRenderFlags, G_N_ELEMENTS(actionsRenderFlags), app); - gtk_action_group_add_toggle_actions(app->agLabel, actionsLabelFlags, G_N_ELEMENTS(actionsLabelFlags), app); - gtk_action_group_add_toggle_actions(app->agOrbit, actionsOrbitFlags, G_N_ELEMENTS(actionsOrbitFlags), app); + gtk_action_group_add_actions(app->agMain, actionsPlain.data(), static_cast(actionsPlain.size()), app); + gtk_action_group_add_toggle_actions(app->agMain, actionsToggle.data(), static_cast(actionsToggle.size()), app); + gtk_action_group_add_radio_actions(app->agVerbosity, actionsVerbosity.data(), static_cast(actionsVerbosity.size()), 0, G_CALLBACK(actionVerbosity), app); + gtk_action_group_add_radio_actions(app->agStarStyle, actionsStarStyle.data(), static_cast(actionsStarStyle.size()), 0, G_CALLBACK(actionStarStyle), app); + gtk_action_group_add_radio_actions(app->agAmbient, actionsAmbientLight.data(), static_cast(actionsAmbientLight.size()), 0, G_CALLBACK(actionAmbientLight), app); + gtk_action_group_add_toggle_actions(app->agRender, actionsRenderFlags.data(), static_cast(actionsRenderFlags.size()), app); + gtk_action_group_add_toggle_actions(app->agLabel, actionsLabelFlags.data(), static_cast(actionsLabelFlags.size()), app); + gtk_action_group_add_toggle_actions(app->agOrbit, actionsOrbitFlags.data(), static_cast(actionsOrbitFlags.size()), app); ui_manager = gtk_ui_manager_new(); gtk_ui_manager_insert_action_group(ui_manager, app->agMain, 0); @@ -129,7 +119,7 @@ static void createMainMenu(GtkWidget* window, AppData* app) accel_group = gtk_ui_manager_get_accel_group(ui_manager); gtk_window_add_accel_group(GTK_WINDOW (window), accel_group); - error = NULL; + error = nullptr; if (!gtk_ui_manager_add_ui_from_file(ui_manager, "celestiaui.xml", &error)) { g_message("Building menus failed: %s", error->message); @@ -140,7 +130,6 @@ static void createMainMenu(GtkWidget* window, AppData* app) app->mainMenu = gtk_ui_manager_get_widget(ui_manager, "/MainMenu"); } - /* Our own watcher. Celestiacore will call notifyChange() to tell us * we need to recheck the check menu items and option buttons. */ @@ -158,7 +147,8 @@ GtkWatcher::GtkWatcher(CelestiaCore* _appCore, AppData* _app) : { } -void GtkWatcher::notifyChange(CelestiaCore*, int property) +void +GtkWatcher::notifyChange(CelestiaCore*, int property) { if (property & CelestiaCore::LabelFlagsChanged) resyncLabelActions(app); @@ -242,10 +232,10 @@ class GtkAlerter : public CelestiaCore::Alerter } }; - /* CALLBACK: Event "realize" on the main GL area. Things that go here are those * that require the glArea to be set up. */ -static void initRealize(GtkWidget* widget, AppData* app) +void +initRealize(GtkWidget* widget, AppData* app) { #ifdef GL_ES constexpr int reqVersion = gl::GLES_2; @@ -271,15 +261,11 @@ static void initRealize(GtkWidget* widget, AppData* app) if (!app->core->initRenderer()) { - cerr << "Failed to initialize renderer.\n"; + std::cerr << "Failed to initialize renderer.\n"; } /* Read/Apply Settings */ - #ifdef GNOME - applySettingsGConfMain(app, app->client); - #else applySettingsFileMain(app, app->settingsFile); - #endif /* GNOME */ /* Synchronize all actions with core settings */ resyncLabelActions(app); @@ -294,7 +280,7 @@ static void initRealize(GtkWidget* widget, AppData* app) gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(app->agMain, "FullScreen")), TRUE); /* If URL at startup, make it so. */ - if (app->startURL != NULL) + if (app->startURL != nullptr) app->core->setStartURL(app->startURL); /* Set simulation time */ @@ -309,10 +295,15 @@ static void initRealize(GtkWidget* widget, AppData* app) gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new(GDK_CROSSHAIR)); } +} // end unnamed namespace + +} // end namespace celestia::gtk /* MAIN */ int main(int argc, char* argv[]) { + using namespace celestia::gtk; + setlocale(LC_ALL, ""); /* Force number displays into C locale. */ setlocale(LC_NUMERIC, "C"); @@ -336,16 +327,16 @@ int main(int argc, char* argv[]) app->lastY = 0; app->showLocalTime = FALSE; app->fullScreen = FALSE; - app->startURL = NULL; + app->startURL = nullptr; /* Command line option parsing */ - GError *error = NULL; + GError *error = nullptr; GOptionContext* context = g_option_context_new(""); - g_option_context_add_main_entries(context, optionEntries, NULL); + g_option_context_add_main_entries(context, optionEntries.data(), nullptr); g_option_context_add_group(context, gtk_get_option_group(TRUE)); g_option_context_parse(context, &argc, &argv, &error); - if (error != NULL) + if (error != nullptr) { g_print("Error in command line options. Use --help for full list.\n"); exit(1); @@ -360,25 +351,18 @@ int main(int argc, char* argv[]) if (argc > 1) app->startURL = argv[argc - 1]; - #ifdef GNOME - /* GNOME Initialization */ - GnomeProgram *program; - program = gnome_program_init("Celestia", VERSION, LIBGNOMEUI_MODULE, - argc, argv, GNOME_PARAM_NONE); - #else /* GTK-Only Initialization */ gtk_init(&argc, &argv); - #endif /* Turn on the splash screen */ SplashData* ss = splashStart(app, !noSplash, installDir, CONFIG_DATA_DIR); splashSetText(ss, "Initializing..."); - if (installDir == NULL) + if (installDir == nullptr) installDir = (gchar*)CONFIG_DATA_DIR; if (chdir(installDir) == -1) - cerr << "Cannot chdir to '" << installDir << "', probably due to improper installation.\n"; + std::cerr << "Cannot chdir to '" << installDir << "', probably due to improper installation.\n"; app->core = new CelestiaCore(); @@ -386,16 +370,16 @@ int main(int argc, char* argv[]) g_assert(app->renderer); /* Parse simulation arguments */ - string altConfig; - if (configFile != NULL) - altConfig = string(configFile); + std::string altConfig; + if (configFile != nullptr) + altConfig = std::string(configFile); - vector configDirs; - if (extrasDir != NULL) + std::vector configDirs; + if (extrasDir != nullptr) { /* Add each extrasDir to the vector */ int i = 0; - while (extrasDir[i] != NULL) + while (extrasDir[i] != nullptr) { configDirs.push_back(extrasDir[i]); i++; @@ -412,14 +396,9 @@ int main(int argc, char* argv[]) app->renderer->setSolarSystemMaxDistance(app->core->getConfig()->renderDetails.SolarSystemMaxDistance); app->renderer->setShadowMapSize(app->core->getConfig()->renderDetails.ShadowMapSize); - #ifdef GNOME - /* Create the main window (GNOME) */ - app->mainWindow = gnome_app_new("Celestia", "Celestia"); - #else /* Create the main window (GTK) */ app->mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(app->mainWindow), "Celestia"); - #endif /* GNOME */ /* Set pointer to AppData structure. This is for when a function is in a * *real* bind to get at this structure. */ @@ -439,7 +418,7 @@ int main(int argc, char* argv[]) GdkGLConfig* glconfig = gdk_gl_config_new_by_mode(static_cast (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE)); - if (glconfig == NULL) + if (glconfig == nullptr) { g_print("*** Cannot find the double-buffered visual.\n"); g_print("*** Trying single-buffered visual.\n"); @@ -447,7 +426,7 @@ int main(int argc, char* argv[]) /* Try single-buffered visual */ glconfig = gdk_gl_config_new_by_mode(static_cast (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH)); - if (glconfig == NULL) + if (glconfig == nullptr) { g_print ("*** No appropriate OpenGL-capable visual found.\n"); exit(1); @@ -456,11 +435,7 @@ int main(int argc, char* argv[]) #endif /* Initialize settings system */ - #ifdef GNOME - initSettingsGConf(app); - #else initSettingsFile(app); - #endif /* GNOME */ /* Create area to be used for OpenGL display */ app->glArea = gtk_drawing_area_new(); @@ -469,7 +444,7 @@ int main(int argc, char* argv[]) #ifdef GTKGLEXT gtk_widget_set_gl_capability(app->glArea, glconfig, - NULL, + nullptr, TRUE, GDK_GL_RGBA_TYPE); #else @@ -494,11 +469,7 @@ int main(int argc, char* argv[]) GDK_POINTER_MOTION_MASK); /* Load settings the can be applied before the simulation is initialized */ - #ifdef GNOME - applySettingsGConfPre(app, app->client); - #else applySettingsFilePre(app, app->settingsFile); - #endif /* GNOME */ /* Full-Screen option from the command line (overrides above). */ if (fullScreen) @@ -520,18 +491,13 @@ int main(int argc, char* argv[]) /* Set context menu handler for the core */ app->core->setContextMenuHandler(handler); - #ifdef GNOME - /* Set window contents (GNOME) */ - gnome_app_set_contents((GnomeApp *)app->mainWindow, GTK_WIDGET(mainBox)); - #else /* Set window contents (GTK) */ gtk_container_add(GTK_CONTAINER(app->mainWindow), GTK_WIDGET(mainBox)); - #endif /* GNOME */ gtk_box_pack_start(GTK_BOX(mainBox), app->mainMenu, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(mainBox), app->glArea, TRUE, TRUE, 0); - gtk_window_set_default_icon_from_file("celestia-logo.png", NULL); + gtk_window_set_default_icon_from_file("celestia-logo.png", nullptr); /* Set focus to glArea widget */ gtk_widget_set_can_focus(GTK_WIDGET(app->glArea), true); @@ -548,10 +514,6 @@ int main(int argc, char* argv[]) /* HACK: Now that window is drawn, set minimum window size */ gtk_widget_set_size_request(app->glArea, 320, 240); - #ifdef GNOME - initSettingsGConfNotifiers(app); - #endif /* GNOME */ - /* Set the ready flag */ app->bReady = TRUE; @@ -565,12 +527,12 @@ int main(int argc, char* argv[]) return 0; } - #ifdef WIN32 -int APIENTRY WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) +int APIENTRY +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { return main(__argc, __argv); } diff --git a/src/celestia/gtk/menu-context.cpp b/src/celestia/gtk/menu-context.cpp index dc76089eda..a80e4f59dc 100644 --- a/src/celestia/gtk/menu-context.cpp +++ b/src/celestia/gtk/menu-context.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include +#include #include @@ -24,142 +27,30 @@ #include "actions.h" #include "common.h" -using namespace std; - -/* Definitions: Callbacks */ -static void wrapAction(GtkAction* action); -static void menuMark(); -static void menuUnMark(); -static void handleContextPrimary(); -static void handleContextPlanet(gpointer data); -static void handleContextSurface(gpointer data); - -/* Definitions: Helpers */ -static GtkMenuItem* AppendMenu(GtkWidget* parent, GCallback callback, const gchar* name, gpointer extra); -static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySystem* psys); -template -static GtkMenu* CreateAlternateSurfaceMenu(const T& surfaces); - - -/* There is no way to pass the AppData struct to the menu at this time. This - * keeps the global variable local to this file, at least conceptually. */ -static AppData* app; - - -/* Initializer. Sets the appData */ -GTKContextMenuHandler::GTKContextMenuHandler(AppData* _app) : - CelestiaCore::ContextMenuHandler() +namespace celestia::gtk { - // FIXME: a workaround to have it referenced by any menu callback - app = _app; -} - -/* ENTRY: Context menu (event handled by appCore) - * Normally, float x and y, but unused, so removed. */ -void GTKContextMenuHandler::requestContextMenu(float, float, Selection sel) +namespace { - GtkWidget* popup = gtk_menu_new(); - string name; - - switch (sel.getType()) - { - case SelectionType::Body: - { - name = sel.body()->getName(); - AppendMenu(popup, NULL, name.c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); - AppendMenu(popup, NULL, NULL, 0); - AppendMenu(popup, NULL, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); - AppendMenu(popup, NULL, "_Follow", gtk_action_group_get_action(app->agMain, "FollowSelection")); - AppendMenu(popup, NULL, "S_ync Orbit", gtk_action_group_get_action(app->agMain, "SyncSelection")); - /* Add info eventually: - * AppendMenu(popup, NULL, "_Info", 0); */ - if (Helper::hasPrimary(sel.body())) - { - AppendMenu(popup, G_CALLBACK(handleContextPrimary), "Select _Primary Body", NULL); - } - - if (const PlanetarySystem* satellites = sel.body()->getSatellites(); - satellites != nullptr && satellites->getSystemSize() != 0) - { - GtkMenu* satMenu = CreatePlanetarySystemMenu(name, satellites); - gtk_menu_item_set_submenu(AppendMenu(popup, NULL, "_Satellites", 0), GTK_WIDGET(satMenu)); - } - - if (auto altSurfaces = sel.body()->getAlternateSurfaceNames(); - altSurfaces.has_value() && !altSurfaces->empty()) - { - GtkMenu* surfMenu = CreateAlternateSurfaceMenu(*altSurfaces); - gtk_menu_item_set_submenu(AppendMenu(popup, NULL, "_Alternate Surfaces", 0), GTK_WIDGET(surfMenu)); - } - } - break; - - case SelectionType::Star: - { - Simulation* sim = app->simulation; - name = ReplaceGreekLetterAbbr(sim->getUniverse()->getStarCatalog()->getStarName(*(sel.star()))); - AppendMenu(popup, NULL, name.c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); - AppendMenu(popup, NULL, NULL, 0); - AppendMenu(popup, NULL, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); - /* Add info eventually: - * AppendMenu(popup, NULL, "_Info", 0); */ - - const SolarSystem* solarSys = sim->getUniverse()->getSolarSystem(sel.star()); - if (solarSys != nullptr) - { - GtkMenu* planetsMenu = CreatePlanetarySystemMenu(name, solarSys->getPlanets()); - if (name == "Sol") - gtk_menu_item_set_submenu(AppendMenu(popup, NULL, "Orbiting Bodies", 0), GTK_WIDGET(planetsMenu)); - else - gtk_menu_item_set_submenu(AppendMenu(popup, NULL, "Planets", 0), GTK_WIDGET(planetsMenu)); - } - } - break; - - case SelectionType::DeepSky: - { - AppendMenu(popup, NULL, app->simulation->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky()).c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); - AppendMenu(popup, NULL, NULL, 0); - AppendMenu(popup, NULL, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); - AppendMenu(popup, NULL, "_Follow", gtk_action_group_get_action(app->agMain, "FollowSelection")); - /* Add info eventually: - * AppendMenu(popup, NULL, "_Info", 0); */ - } - break; - - case SelectionType::Location: - break; - - default: - break; - } - - if (app->simulation->getUniverse()->isMarked(sel, 1)) - AppendMenu(popup, menuUnMark, "_Unmark", 0); - else - AppendMenu(popup, menuMark, "_Mark", 0); - - app->simulation->setSelection(sel); - - gtk_widget_show_all(popup); - gtk_menu_popup(GTK_MENU(popup), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); -} +/* There is no way to pass the AppData struct to the menu at this time. This + * keeps the global variable local to this file, at least conceptually. */ +AppData* app; /* CALLBACK: Wrap a GtkAction. The whole context menu should be replaced at * some point */ -static void wrapAction(GtkAction* action) +void +wrapAction(GtkAction* action) { gtk_action_activate(action); } - /* CALLBACK: Mark the selected object. Might some day be a GtkAction. */ -static void menuMark() +void +menuMark() { Simulation* sim = app->simulation; - if (sim->getUniverse() != NULL) + if (sim->getUniverse() != nullptr) { using namespace celestia; MarkerRepresentation markerRep(MarkerRepresentation::Diamond, 10.0f, Color(0.0f, 1.0f, 0.0f, 0.9f)); @@ -167,18 +58,18 @@ static void menuMark() } } - /* CALLBACK: Unmark the selected object. Might some day be a GtkAction. */ -static void menuUnMark() +void +menuUnMark() { Simulation* sim = app->simulation; - if (sim->getUniverse() != NULL) + if (sim->getUniverse() != nullptr) sim->getUniverse()->unmarkObject(sim->getSelection(), 1); } - /* CALLBACK: Handle a planetary selection from the context menu. */ -static void handleContextPlanet(gpointer data) +void +handleContextPlanet(gpointer data) { int value = GPOINTER_TO_INT(data); @@ -210,20 +101,20 @@ static void handleContextPlanet(gpointer data) } } - /* CALLBACK: Handle an object's primary selection */ -static void handleContextPrimary() +void +handleContextPrimary() { Selection sel = app->simulation->getSelection(); - if (sel.body() != NULL) + if (sel.body() != nullptr) { app->simulation->setSelection(Helper::getPrimary(sel.body())); } } - /* CALLBACK: Handle an alternate surface from the context menu. */ -static void handleContextSurface(gpointer data) +void +handleContextSurface(gpointer data) { int value = GPOINTER_TO_INT(data); @@ -250,21 +141,21 @@ static void handleContextSurface(gpointer data) } } - /* HELPER: Append a menu item and return pointer. Used for context menu. */ -static GtkMenuItem* AppendMenu(GtkWidget* parent, GCallback callback, const gchar* name, gpointer extra) +GtkMenuItem* +AppendMenu(GtkWidget* parent, GCallback callback, const gchar* name, gpointer extra) { GtkWidget* menuitem; gpointer data; /* Check for separator */ - if (name == NULL) + if (name == nullptr) menuitem = gtk_separator_menu_item_new(); else menuitem = gtk_menu_item_new_with_mnemonic(name); /* If no callback was provided, pass GtkAction, else convert to pointer */ - if (callback == NULL && extra != 0) + if (callback == nullptr && extra != 0) { callback = G_CALLBACK(wrapAction); data = extra; @@ -273,7 +164,7 @@ static GtkMenuItem* AppendMenu(GtkWidget* parent, GCallback callback, const gcha data = GINT_TO_POINTER(extra); /* Add handler */ - if (callback != NULL) + if (callback != nullptr) g_signal_connect_swapped (G_OBJECT(menuitem), "activate", G_CALLBACK(callback), data); @@ -282,16 +173,15 @@ static GtkMenuItem* AppendMenu(GtkWidget* parent, GCallback callback, const gcha return GTK_MENU_ITEM(menuitem); } - /* Typedefs and structs for sorting objects by name in context menu. */ -typedef pair IntStrPair; -typedef vector IntStrPairVec; +using IntStrPair = std::pair; +using IntStrPairVec = std::vector; struct IntStrPairComparePredicate { IntStrPairComparePredicate() : dummy(0) {} - bool operator()(const IntStrPair pair1, const IntStrPair pair2) const + bool operator()(const IntStrPair& pair1, const IntStrPair& pair2) const { return (pair1.second.compare(pair2.second) < 0); } @@ -300,7 +190,8 @@ struct IntStrPairComparePredicate }; /* HELPER: Create planetary submenu for context menu, return menu pointer. */ -static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySystem* psys) +GtkMenu* +CreatePlanetarySystemMenu(const std::string& parentName, const PlanetarySystem* psys) { /* * Modified from winmain.cpp @@ -313,18 +204,18 @@ static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySyst */ /* Declare vector> objects for each classification of body */ - vector asteroids; - vector comets; - vector invisibles; - vector moons; - vector minorMoons; - vector planets; - vector dwarfPlanets; - vector spacecraft; + std::vector asteroids; + std::vector comets; + std::vector invisibles; + std::vector moons; + std::vector minorMoons; + std::vector planets; + std::vector dwarfPlanets; + std::vector spacecraft; /* We will use these objects to iterate over all the above vectors */ - vector objects; - vector menuNames; + std::vector objects; + std::vector menuNames; /* Place each body in the correct vector based on classification */ GtkWidget* menu = gtk_menu_new(); @@ -380,9 +271,9 @@ static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySyst /* Now sort each vector and generate submenus */ IntStrPairComparePredicate pred; - vector::iterator obj; - vector::iterator it; - vector::iterator menuName; + std::vector::iterator obj; + std::vector::iterator it; + std::vector::iterator menuName; GtkWidget* subMenu; int numSubMenus; @@ -421,7 +312,7 @@ static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySyst for(it=obj->begin(); it != obj->end(); it++) AppendMenu(subMenu, G_CALLBACK(handleContextPlanet), it->second.c_str(), GINT_TO_POINTER(it->first)); - gtk_menu_item_set_submenu(AppendMenu(menu, NULL, menuName->c_str(), 0), GTK_WIDGET(subMenu)); + gtk_menu_item_set_submenu(AppendMenu(menu, nullptr, menuName->c_str(), 0), GTK_WIDGET(subMenu)); } else { @@ -437,10 +328,10 @@ static GtkMenu* CreatePlanetarySystemMenu(string parentName, const PlanetarySyst return GTK_MENU(menu); } - /* HELPER: Create surface submenu for context menu, return menu pointer. */ template -static GtkMenu* CreateAlternateSurfaceMenu(const T& surfaces) +GtkMenu* +CreateAlternateSurfaceMenu(const T& surfaces) { GtkWidget* menu = gtk_menu_new(); @@ -454,3 +345,106 @@ static GtkMenu* CreateAlternateSurfaceMenu(const T& surfaces) return GTK_MENU(menu); } + +} // end unnamed namespace + +/* Initializer. Sets the appData */ +GTKContextMenuHandler::GTKContextMenuHandler(AppData* _app) : + CelestiaCore::ContextMenuHandler() +{ + // FIXME: a workaround to have it referenced by any menu callback + app = _app; +} + +/* ENTRY: Context menu (event handled by appCore) + * Normally, float x and y, but unused, so removed. */ +void GTKContextMenuHandler::requestContextMenu(float, float, Selection sel) +{ + GtkWidget* popup = gtk_menu_new(); + std::string name; + + switch (sel.getType()) + { + case SelectionType::Body: + { + name = sel.body()->getName(); + AppendMenu(popup, nullptr, name.c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); + AppendMenu(popup, nullptr, nullptr, 0); + AppendMenu(popup, nullptr, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); + AppendMenu(popup, nullptr, "_Follow", gtk_action_group_get_action(app->agMain, "FollowSelection")); + AppendMenu(popup, nullptr, "S_ync Orbit", gtk_action_group_get_action(app->agMain, "SyncSelection")); + /* Add info eventually: + * AppendMenu(popup, nullptr, "_Info", 0); */ + if (Helper::hasPrimary(sel.body())) + { + AppendMenu(popup, G_CALLBACK(handleContextPrimary), "Select _Primary Body", nullptr); + } + + if (const PlanetarySystem* satellites = sel.body()->getSatellites(); + satellites != nullptr && satellites->getSystemSize() != 0) + { + GtkMenu* satMenu = CreatePlanetarySystemMenu(name, satellites); + gtk_menu_item_set_submenu(AppendMenu(popup, nullptr, "_Satellites", 0), GTK_WIDGET(satMenu)); + } + + if (auto altSurfaces = sel.body()->getAlternateSurfaceNames(); + altSurfaces.has_value() && !altSurfaces->empty()) + { + GtkMenu* surfMenu = CreateAlternateSurfaceMenu(*altSurfaces); + gtk_menu_item_set_submenu(AppendMenu(popup, nullptr, "_Alternate Surfaces", 0), GTK_WIDGET(surfMenu)); + } + } + break; + + case SelectionType::Star: + { + Simulation* sim = app->simulation; + name = ReplaceGreekLetterAbbr(sim->getUniverse()->getStarCatalog()->getStarName(*(sel.star()))); + AppendMenu(popup, nullptr, name.c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); + AppendMenu(popup, nullptr, nullptr, 0); + AppendMenu(popup, nullptr, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); + /* Add info eventually: + * AppendMenu(popup, nullptr, "_Info", 0); */ + + const SolarSystem* solarSys = sim->getUniverse()->getSolarSystem(sel.star()); + if (solarSys != nullptr) + { + GtkMenu* planetsMenu = CreatePlanetarySystemMenu(name, solarSys->getPlanets()); + if (name == "Sol") + gtk_menu_item_set_submenu(AppendMenu(popup, nullptr, "Orbiting Bodies", 0), GTK_WIDGET(planetsMenu)); + else + gtk_menu_item_set_submenu(AppendMenu(popup, nullptr, "Planets", 0), GTK_WIDGET(planetsMenu)); + } + } + break; + + case SelectionType::DeepSky: + { + AppendMenu(popup, nullptr, app->simulation->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky()).c_str(), gtk_action_group_get_action(app->agMain, "CenterSelection")); + AppendMenu(popup, nullptr, nullptr, 0); + AppendMenu(popup, nullptr, "_Goto", gtk_action_group_get_action(app->agMain, "GotoSelection")); + AppendMenu(popup, nullptr, "_Follow", gtk_action_group_get_action(app->agMain, "FollowSelection")); + /* Add info eventually: + * AppendMenu(popup, nullptr, "_Info", 0); */ + } + break; + + case SelectionType::Location: + break; + + default: + break; + } + + if (app->simulation->getUniverse()->isMarked(sel, 1)) + AppendMenu(popup, menuUnMark, "_Unmark", 0); + else + AppendMenu(popup, menuMark, "_Mark", 0); + + app->simulation->setSelection(sel); + + gtk_widget_show_all(popup); + gtk_menu_popup(GTK_MENU(popup), nullptr, nullptr, nullptr, nullptr, 0, gtk_get_current_event_time()); +} + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/menu-context.h b/src/celestia/gtk/menu-context.h index f4fd72dd93..6f91388041 100644 --- a/src/celestia/gtk/menu-context.h +++ b/src/celestia/gtk/menu-context.h @@ -20,6 +20,9 @@ #include "common.h" +namespace celestia::gtk +{ + class GTKContextMenuHandler : public CelestiaCore::ContextMenuHandler { public: @@ -27,3 +30,5 @@ class GTKContextMenuHandler : public CelestiaCore::ContextMenuHandler void requestContextMenu(float, float, Selection sel); }; + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/settings-file.cpp b/src/celestia/gtk/settings-file.cpp index 87e8567b43..8cdfae500c 100644 --- a/src/celestia/gtk/settings-file.cpp +++ b/src/celestia/gtk/settings-file.cpp @@ -10,6 +10,9 @@ * $Id: settings-file.cpp,v 1.5 2008-01-18 04:36:11 suwalski Exp $ */ +#include +#include + #include #include @@ -19,24 +22,51 @@ #include "settings-file.h" #include "common.h" +namespace celestia::gtk +{ + +namespace +{ + +/* HELPER: gets an or-group flag and handles error checking */ +void +getFlag(GKeyFile* file, int *flags, int setting, const gchar* section, const gchar* key, int* errors) +{ + GError* e = nullptr; + + *flags |= setting * g_key_file_get_boolean(file, section, key, &e); + + if (e != nullptr) + *errors += 1; +} + +void +getFlag64(GKeyFile* file, std::uint64_t *flags, std::uint64_t setting, const gchar* section, const gchar* key, int* errors) +{ + GError* e = nullptr; + + *flags |= setting * g_key_file_get_boolean(file, section, key, &e); + + if (e != nullptr) + *errors += 1; +} -/* Definitions: Helpers */ -static void getFlag(GKeyFile* file, int *flags, int setting, const gchar* section, const gchar* key, int* errors); -static void getFlag64(GKeyFile* file, uint64_t *flags, uint64_t setting, const gchar* section, const gchar* key, int* errors); +} // end unnamed namespace /* ENTRY: Initializes and reads into memory the preferences */ -void initSettingsFile(AppData* app) +void +initSettingsFile(AppData* app) { - GError *error = NULL; + GError *error = nullptr; app->settingsFile = g_key_file_new(); - char* fn = g_build_filename(g_get_home_dir(), CELESTIARC, NULL); + char* fn = g_build_filename(g_get_home_dir(), CELESTIARC, nullptr); g_key_file_load_from_file(app->settingsFile, fn, G_KEY_FILE_NONE, &error); /* Should check G_KEY_FILE_ERROR_NOT_FOUND, but bug in glib returns wrong * error code. */ - if (error != NULL && g_file_test(fn, G_FILE_TEST_EXISTS)) + if (error != nullptr && g_file_test(fn, G_FILE_TEST_EXISTS)) { g_print("Error reading '%s': %s.\n", fn, error->message); exit(1); @@ -45,9 +75,9 @@ void initSettingsFile(AppData* app) g_free(fn); } - /* ENTRY: Applies preferences needed before initializing the core */ -void applySettingsFilePre(AppData* app, GKeyFile* file) +void +applySettingsFilePre(AppData* app, GKeyFile* file) { int sizeX, sizeY, positionX, positionY; GError* e; @@ -55,26 +85,26 @@ void applySettingsFilePre(AppData* app, GKeyFile* file) /* Numbers require special treatment because if they are not found they * are not set to NULL like strings. So, if that is the case, we set them * to values that will cause setSane*() to set defaults. */ - e= NULL; + e= nullptr; sizeX = g_key_file_get_integer(file, "Window", "width", &e); - if (e != NULL) sizeX = -1; + if (e != nullptr) sizeX = -1; - e= NULL; + e= nullptr; sizeY = g_key_file_get_integer(file, "Window", "height", &e); - if (e != NULL) sizeY = -1; + if (e != nullptr) sizeY = -1; - e= NULL; + e= nullptr; positionX = g_key_file_get_integer(file, "Window", "x", &e); - if (e != NULL) positionX = -1; + if (e != nullptr) positionX = -1; - e= NULL; + e= nullptr; positionY = g_key_file_get_integer(file, "Window", "y", &e); - if (e != NULL) positionY = -1; + if (e != nullptr) positionY = -1; /* These next two cannot be checked for sanity, default set here */ - e= NULL; + e= nullptr; app->fullScreen = g_key_file_get_boolean(file, "Window", "fullScreen", &e); - if (e != NULL) app->fullScreen = FALSE; + if (e != nullptr) app->fullScreen = FALSE; /* Nothing is set here. The prefs structure is used to set things at the * corrent times. */ @@ -82,47 +112,47 @@ void applySettingsFilePre(AppData* app, GKeyFile* file) setSaneWinPosition(app, positionX, positionY); } - /* ENTRY: Applies preferences after the core is initialized */ -void applySettingsFileMain(AppData* app, GKeyFile* file) +void +applySettingsFileMain(AppData* app, GKeyFile* file) { GError* e; float ambientLight, visualMagnitude, galaxyLightGain; int errors, verbosity, starStyle, textureResolution, distanceLimit, om, lm; - uint64_t rf; + std::uint64_t rf; /* See comment in applySettingsFilePrefs() */ - e = NULL; + e = nullptr; ambientLight = (float)g_key_file_get_integer(file, "Main", "ambientLight", &e) / 1000.0; - if (e != NULL) ambientLight = -1.0; + if (e != nullptr) ambientLight = -1.0; - e = NULL; + e = nullptr; visualMagnitude = (float)g_key_file_get_integer(file, "Main", "visualMagnitude", &e) / 1000.0; - if (e != NULL) visualMagnitude = -1.0; + if (e != nullptr) visualMagnitude = -1.0; - e = NULL; + e = nullptr; galaxyLightGain = (float)g_key_file_get_integer(file, "Main", "galaxyLightGain", &e) / 1000.0; - if (e != NULL) galaxyLightGain = -1.0; + if (e != nullptr) galaxyLightGain = -1.0; - e = NULL; + e = nullptr; distanceLimit = g_key_file_get_integer(file, "Main", "distanceLimit", &e); - if (e != NULL) distanceLimit = -1; + if (e != nullptr) distanceLimit = -1; - e = NULL; + e = nullptr; verbosity = g_key_file_get_integer(file, "Main", "verbosity", &e); - if (e != NULL) verbosity = -1; + if (e != nullptr) verbosity = -1; - e = NULL; + e = nullptr; starStyle = g_key_file_get_integer(file, "Main", "starStyle", &e); - if (e != NULL) starStyle = -1; + if (e != nullptr) starStyle = -1; - e = NULL; + e = nullptr; textureResolution = g_key_file_get_integer(file, "Main", "textureResolution", &e); - if (e != NULL) textureResolution = -1; + if (e != nullptr) textureResolution = -1; - e = NULL; + e = nullptr; app->showLocalTime = g_key_file_get_boolean(file, "Main", "localTime", &e); - if (e != NULL) app->showLocalTime = FALSE; + if (e != nullptr) app->showLocalTime = FALSE; /* All settings that need sanity checks get them */ setSaneAmbientLight(app, ambientLight); @@ -132,7 +162,7 @@ void applySettingsFileMain(AppData* app, GKeyFile* file) setSaneVerbosity(app, verbosity); setSaneStarStyle(app, (Renderer::StarStyle)starStyle); setSaneTextureResolution(app, textureResolution); - setSaneAltSurface(app, g_key_file_get_string(file, "Main", "altSurfaceName", NULL)); + setSaneAltSurface(app, g_key_file_get_string(file, "Main", "altSurfaceName", nullptr)); /* Render Flags */ errors = 0; @@ -215,32 +245,32 @@ void applySettingsFileMain(AppData* app, GKeyFile* file) app->renderer->setLabelMode(lm); } - /* ENTRY: Saves settings to file */ -void saveSettingsFile(AppData* app) +void +saveSettingsFile(AppData* app) { int om, lm; - uint64_t rf; + std::uint64_t rf; GKeyFile* file = app->settingsFile; - char* fn = g_build_filename(g_get_home_dir(), CELESTIARC, NULL); - FILE* outfile; + char* fn = g_build_filename(g_get_home_dir(), CELESTIARC, nullptr); + std::FILE* outfile; g_key_file_set_integer(file, "Main", "ambientLight", (int)(1000 * app->renderer->getAmbientLightLevel())); - g_key_file_set_comment(file, "Main", "ambientLight", "ambientLight = (int)(1000 * AmbientLightLevel)", NULL); + g_key_file_set_comment(file, "Main", "ambientLight", "ambientLight = (int)(1000 * AmbientLightLevel)", nullptr); g_key_file_set_integer(file, "Main", "visualMagnitude", (int)(1000 * app->simulation->getFaintestVisible())); - g_key_file_set_comment(file, "Main", "visualMagnitude", "visualMagnitude = (int)(1000 * FaintestVisible)", NULL); + g_key_file_set_comment(file, "Main", "visualMagnitude", "visualMagnitude = (int)(1000 * FaintestVisible)", nullptr); g_key_file_set_integer(file, "Main", "galaxyLightGain", (int)(1000 * Galaxy::getLightGain())); - g_key_file_set_comment(file, "Main", "galaxyLightGain", "galaxyLightGain = (int)(1000 * GalaxyLightGain)", NULL); + g_key_file_set_comment(file, "Main", "galaxyLightGain", "galaxyLightGain = (int)(1000 * GalaxyLightGain)", nullptr); g_key_file_set_integer(file, "Main", "distanceLimit", (int)app->renderer->getDistanceLimit()); - g_key_file_set_comment(file, "Main", "distanceLimit", "Rendering limit in light-years", NULL); + g_key_file_set_comment(file, "Main", "distanceLimit", "Rendering limit in light-years", nullptr); g_key_file_set_boolean(file, "Main", "localTime", app->showLocalTime); - g_key_file_set_comment(file, "Main", "localTime", "Display time in terms of local time zone", NULL); + g_key_file_set_comment(file, "Main", "localTime", "Display time in terms of local time zone", nullptr); g_key_file_set_integer(file, "Main", "verbosity", app->core->getHudDetail()); - g_key_file_set_comment(file, "Main", "verbosity", "Level of Detail in the heads-up-display. 0=None, 1=Terse, 2=Verbose", NULL); + g_key_file_set_comment(file, "Main", "verbosity", "Level of Detail in the heads-up-display. 0=None, 1=Terse, 2=Verbose", nullptr); g_key_file_set_integer(file, "Main", "starStyle", app->renderer->getStarStyle()); - g_key_file_set_comment(file, "Main", "starStyle", "Style of star rendering. 0=Fuzzy Points, 1=Points, 2=Scaled Discs", NULL); + g_key_file_set_comment(file, "Main", "starStyle", "Style of star rendering. 0=Fuzzy Points, 1=Points, 2=Scaled Discs", nullptr); g_key_file_set_integer(file, "Main", "textureResolution", app->renderer->getResolution()); - g_key_file_set_comment(file, "Main", "textureResolution", "Resolution of textures. 0=Low, 1=Medium, 2=High", NULL); + g_key_file_set_comment(file, "Main", "textureResolution", "Resolution of textures. 0=Low, 1=Medium, 2=High", nullptr); g_key_file_set_string(file, "Main", "altSurfaceName", app->simulation->getActiveObserver()->getDisplayedSurface().c_str()); g_key_file_set_integer(file, "Window", "width", getWinWidth(app)); @@ -308,40 +338,19 @@ void saveSettingsFile(AppData* app) g_key_file_set_boolean(file, "LabelMode", "i18n", lm & Renderer::I18nConstellationLabels); g_key_file_set_boolean(file, "LabelMode", "globular", lm & Renderer::GlobularLabels); - g_key_file_set_comment(file, "RenderFlags", NULL, "All Render Flag values must be true or false", NULL); - g_key_file_set_comment(file, "OrbitMask", NULL, "All Orbit Mask values must be true or false", NULL); - g_key_file_set_comment(file, "LabelMode", NULL, "All Label Mode values must be true or false", NULL); + g_key_file_set_comment(file, "RenderFlags", nullptr, "All Render Flag values must be true or false", nullptr); + g_key_file_set_comment(file, "OrbitMask", nullptr, "All Orbit Mask values must be true or false", nullptr); + g_key_file_set_comment(file, "LabelMode", nullptr, "All Label Mode values must be true or false", nullptr); /* Write the settings to a file */ - outfile = fopen(fn, "w"); + outfile = std::fopen(fn, "w"); - if (outfile == NULL) + if (outfile == nullptr) g_print("Error writing '%s'.\n", fn); - fputs(g_key_file_to_data(file, NULL, NULL), outfile); + std::fputs(g_key_file_to_data(file, nullptr, nullptr), outfile); g_free(fn); } - -/* HELPER: gets an or-group flag and handles error checking */ -static void getFlag(GKeyFile* file, int *flags, int setting, const gchar* section, const gchar* key, int* errors) -{ - GError* e = NULL; - - *flags |= setting * g_key_file_get_boolean(file, section, key, &e); - - if (e != NULL) - *errors += 1; -} - - -static void getFlag64(GKeyFile* file, uint64_t *flags, uint64_t setting, const gchar* section, const gchar* key, int* errors) -{ - GError* e = NULL; - - *flags |= setting * g_key_file_get_boolean(file, section, key, &e); - - if (e != NULL) - *errors += 1; -} +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/settings-file.h b/src/celestia/gtk/settings-file.h index 34df15763a..174bad68a6 100644 --- a/src/celestia/gtk/settings-file.h +++ b/src/celestia/gtk/settings-file.h @@ -16,9 +16,11 @@ #include "common.h" - #define CELESTIARC ".celestiarc" +namespace celestia::gtk +{ + /* Initialize Settings File */ void initSettingsFile(AppData* app); @@ -28,3 +30,5 @@ void applySettingsFileMain(AppData* app, GKeyFile* file); /* Save Settings to File */ void saveSettingsFile(AppData* app); + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/settings-gconf.cpp b/src/celestia/gtk/settings-gconf.cpp deleted file mode 100644 index 39b43e574c..0000000000 --- a/src/celestia/gtk/settings-gconf.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Celestia GTK+ Front-End - * Copyright (C) 2005 Pat Suwalski - * - * This program 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. - * - * $Id: settings-gconf.cpp,v 1.4 2008-01-18 04:36:11 suwalski Exp $ - */ - -#include -#include - -#include -#include -#include - -#include "settings-gconf.h" -#include "common.h" - - -/* Definitions: GConf Callbacks */ -static void confLabels(GConfClient*, guint, GConfEntry*, AppData* app); -static void confRender(GConfClient*, guint, GConfEntry*, AppData* app); -static void confOrbits(GConfClient*, guint, GConfEntry*, AppData* app); -static void confWinWidth(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confWinHeight(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confWinX(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confWinY(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confAmbientLight(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confVisualMagnitude(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confGalaxyLightGain(GConfClient*, guint, GConfEntry* e, AppData*); -static void confDistanceLimit(GConfClient*, guint, GConfEntry* e, AppData*); -static void confShowLocalTime(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confVerbosity(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confFullScreen(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confStarStyle(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confTextureResolution(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confAltSurfaceName(GConfClient*, guint, GConfEntry* e, AppData* app); -static void confVideoSync(GConfClient*, guint, GConfEntry* e, AppData* app); - -/* Definitions: Helpers */ -static int readGConfRender(GConfClient* client); -static int readGConfOrbits(GConfClient* client); -static int readGConfLabels(GConfClient* client); -static void gcSetFlag(int type, const char* name, gboolean value, GConfClient* client); - - -/* ENTRY: Initializes the GConf connection */ -void initSettingsGConf(AppData* app) -{ - app->client = gconf_client_get_default(); - gconf_client_add_dir(app->client, "/apps/celestia", GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); -} - - -/* ENTRY: Connects GConf keys to their callbacks */ -void initSettingsGConfNotifiers(AppData* app) -{ - /* Add preference client notifiers. */ - gconf_client_notify_add (app->client, "/apps/celestia/labels", (GConfClientNotifyFunc)confLabels, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/render", (GConfClientNotifyFunc)confRender, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/orbits", (GConfClientNotifyFunc)confOrbits, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/winWidth", (GConfClientNotifyFunc)confWinWidth, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/winHeight", (GConfClientNotifyFunc)confWinHeight, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/winX", (GConfClientNotifyFunc)confWinX, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/winY", (GConfClientNotifyFunc)confWinY, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/ambientLight", (GConfClientNotifyFunc)confAmbientLight, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/visualMagnitude", (GConfClientNotifyFunc)confVisualMagnitude, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/galaxyLightGain", (GConfClientNotifyFunc)confGalaxyLightGain, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/distanceLimit", (GConfClientNotifyFunc)confDistanceLimit, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/showLocalTime", (GConfClientNotifyFunc)confShowLocalTime, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/verbosity", (GConfClientNotifyFunc)confVerbosity, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/fullScreen", (GConfClientNotifyFunc)confFullScreen, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/starStyle", (GConfClientNotifyFunc)confStarStyle, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/textureResolution", (GConfClientNotifyFunc)confTextureResolution, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/altSurfaceName", (GConfClientNotifyFunc)confAltSurfaceName, app, NULL, NULL); - gconf_client_notify_add (app->client, "/apps/celestia/videoSync", (GConfClientNotifyFunc)confVideoSync, app, NULL, NULL); -} - - -/* ENTRY: Reads preferences required before initializing simulation */ -void applySettingsGConfPre(AppData* app, GConfClient* client) -{ - int sizeX, sizeY, positionX, positionY; - - /* Error checking occurs as values are used */ - sizeX = gconf_client_get_int(client, "/apps/celestia/winWidth", NULL); - sizeY = gconf_client_get_int(client, "/apps/celestia/winHeight", NULL); - positionX = gconf_client_get_int(client, "/apps/celestia/winX", NULL); - positionY = gconf_client_get_int(client, "/apps/celestia/winY", NULL); - app->fullScreen = gconf_client_get_bool(client, "/apps/celestia/fullScreen", NULL); - - setSaneWinSize(app, sizeX, sizeY); - setSaneWinPosition(app, positionX, positionY); -} - - -/* ENTRY: Reads and applies basic preferences */ -void applySettingsGConfMain(AppData* app, GConfClient* client) -{ - int rf, om, lm; - - /* All settings that need sanity checks get them */ - setSaneAmbientLight(app, gconf_client_get_float(client, "/apps/celestia/ambientLight", NULL)); - setSaneVisualMagnitude(app, gconf_client_get_float(client, "/apps/celestia/visualMagnitude", NULL)); - setSaneGalaxyLightGain(gconf_client_get_float(client, "/apps/celestia/galaxyLightGain", NULL)); - setSaneDistanceLimit(app, gconf_client_get_int(client, "/apps/celestia/distanceLimit", NULL)); - setSaneVerbosity(app, gconf_client_get_int(client, "/apps/celestia/verbosity", NULL)); - setSaneStarStyle(app, (Renderer::StarStyle)gconf_client_get_int(client, "/apps/celestia/starStyle", NULL)); - setSaneTextureResolution(app, gconf_client_get_int(client, "/apps/celestia/textureResolution", NULL)); - setSaneAltSurface(app, gconf_client_get_string(client, "/apps/celestia/altSurfaceName", NULL)); - - app->showLocalTime = gconf_client_get_bool(client, "/apps/celestia/showLocalTime", NULL); - - app->renderer->setVideoSync(gconf_client_get_bool(client, "/apps/celestia/videoSync", NULL)); - - /* Render Flags */ - rf = readGConfRender(app->client); - app->renderer->setRenderFlags(rf); - - /* Orbit Mode */ - om = readGConfOrbits(app->client); - app->renderer->setOrbitMask(om); - - /* Label Mode */ - lm = readGConfLabels(app->client); - app->renderer->setLabelMode(lm); -} - - -/* ENTRY: Saves the final settings that are not updated on-the-fly */ -void saveSettingsGConf(AppData* app) -{ - /* Save window position */ - gconf_client_set_int(app->client, "/apps/celestia/winX", getWinX(app), NULL); - gconf_client_set_int(app->client, "/apps/celestia/winY", getWinY(app), NULL); - - /* Save window size */ - gconf_client_set_int(app->client, "/apps/celestia/winWidth", getWinWidth(app), NULL); - gconf_client_set_int(app->client, "/apps/celestia/winHeight", getWinHeight(app), NULL); - - /* These do not produce notification when changed */ - gconf_client_set_int(app->client, "/apps/celestia/textureResolution", app->renderer->getResolution(), NULL); - gconf_client_set_int(app->client, "/apps/celestia/distanceLimit", (int)app->renderer->getDistanceLimit(), NULL); - - g_object_unref (G_OBJECT (app->client)); -} - - -/* UTILITY: Converts a binary render flag to individual keys */ -void gcSetRenderFlag(int flag, gboolean state, GConfClient* client) -{ - switch (flag) - { - case Renderer::ShowStars: gcSetFlag(Render, "stars", state, client); break; - case Renderer::ShowPlanets: gcSetFlag(Render, "planets", state, client); break; - case Renderer::ShowGalaxies: gcSetFlag(Render, "galaxies", state, client); break; - case Renderer::ShowDiagrams: gcSetFlag(Render, "diagrams", state, client); break; - case Renderer::ShowCloudMaps: gcSetFlag(Render, "cloudMaps", state, client); break; - case Renderer::ShowOrbits: gcSetFlag(Render, "orbits", state, client); break; - case Renderer::ShowCelestialSphere: gcSetFlag(Render, "celestialSphere", state, client); break; - case Renderer::ShowNightMaps: gcSetFlag(Render, "nightMaps", state, client); break; - case Renderer::ShowAtmospheres: gcSetFlag(Render, "atmospheres", state, client); break; - case Renderer::ShowSmoothLines: gcSetFlag(Render, "smoothLines", state, client); break; - case Renderer::ShowEclipseShadows: gcSetFlag(Render, "eclipseShadows", state, client); break; - case Renderer::ShowRingShadows: gcSetFlag(Render, "ringShadows", state, client); break; - case Renderer::ShowBoundaries: gcSetFlag(Render, "boundaries", state, client); break; - case Renderer::ShowAutoMag: gcSetFlag(Render, "autoMag", state, client); break; - case Renderer::ShowCometTails: gcSetFlag(Render, "cometTails", state, client); break; - case Renderer::ShowMarkers: gcSetFlag(Render, "markers", state, client); break; - case Renderer::ShowPartialTrajectories: gcSetFlag(Render, "partialTrajectories", state, client); break; - case Renderer::ShowNebulae: gcSetFlag(Render, "nebulae", state, client); break; - case Renderer::ShowOpenClusters: gcSetFlag(Render, "openClusters", state, client); break; - case Renderer::ShowGlobulars: gcSetFlag(Render, "globulars", state, client); break; - case Renderer::ShowGalacticGrid: gcSetFlag(Render, "gridGalactic", state, client); break; - case Renderer::ShowEclipticGrid: gcSetFlag(Render, "gridEcliptic", state, client); break; - case Renderer::ShowHorizonGrid: gcSetFlag(Render, "gridHorizontal", state, client); break; - } -} - - -/* UTILITY: Converts a binary orbit mask to individual keys */ -void gcSetOrbitMask(int flag, gboolean state, GConfClient* client) -{ - switch (flag) - { - case Body::Planet: gcSetFlag(Orbit, "planet", state, client); break; - case Body::Moon: gcSetFlag(Orbit, "moon", state, client); break; - case Body::Asteroid: gcSetFlag(Orbit, "asteroid", state, client); break; - case Body::Spacecraft: gcSetFlag(Orbit, "spacecraft", state, client); break; - case Body::Comet: gcSetFlag(Orbit, "comet", state, client); break; - case Body::Invisible: gcSetFlag(Orbit, "invisible", state, client); break; - case Body::Unknown: gcSetFlag(Orbit, "unknown", state, client); break; - } -} - - -/* UTILITY: Converts a binary label mode to individual keys */ -void gcSetLabelMode(int flag, gboolean state, GConfClient* client) -{ - switch (flag) - { - case Renderer::StarLabels: gcSetFlag(Label, "star", state, client); break; - case Renderer::PlanetLabels: gcSetFlag(Label, "planet", state, client); break; - case Renderer::MoonLabels: gcSetFlag(Label, "moon", state, client); break; - case Renderer::ConstellationLabels: gcSetFlag(Label, "constellation", state, client); break; - case Renderer::GalaxyLabels: gcSetFlag(Label, "galaxy", state, client); break; - case Renderer::AsteroidLabels: gcSetFlag(Label, "asteroid", state, client); break; - case Renderer::SpacecraftLabels: gcSetFlag(Label, "spacecraft", state, client); break; - case Renderer::LocationLabels: gcSetFlag(Label, "location", state, client); break; - case Renderer::CometLabels: gcSetFlag(Label, "comet", state, client); break; - case Renderer::NebulaLabels: gcSetFlag(Label, "nebula", state, client); break; - case Renderer::OpenClusterLabels: gcSetFlag(Label, "openCluster", state, client); break; - case Renderer::I18nConstellationLabels: gcSetFlag(Label, "i18n", state, client); break; - case Renderer::GlobularLabels: gcSetFlag(Label, "globular", state, client); break; - } -} - - -/* GCONF CALLBACK: Reloads labels upon change */ -static void confLabels(GConfClient*, guint, GConfEntry*, AppData* app) -{ - int oldLabels = app->renderer->getLabelMode(); - - /* Reload all the labels */ - int newLabels = readGConfLabels(app->client); - - /* Set label flags */ - if (newLabels != oldLabels) - app->renderer->setLabelMode(newLabels); -} - - -/* GCONF CALLBACK: Reloads render flags upon change */ -static void confRender(GConfClient*, guint, GConfEntry*, AppData* app) -{ - int oldRender = app->renderer->getRenderFlags(); - - /* Reload all the render flags */ - int newRender = readGConfRender(app->client); - - /* Set render flags */ - if (newRender != oldRender) - app->renderer->setRenderFlags(newRender); -} - - -/* GCONF CALLBACK: Reloads orbits upon change */ -static void confOrbits(GConfClient*, guint, GConfEntry*, AppData* app) -{ - int oldOrbit = app->renderer->getOrbitMask(); - - /* Reload all the orbits */ - int newOrbit = readGConfOrbits(app->client); - - /* Set orbit flags */ - if (newOrbit != oldOrbit) - app->renderer->setOrbitMask(newOrbit); -} - - -/* GCONF CALLBACK: Sets window width upon change */ -static void confWinWidth(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int w = gconf_value_get_int(e->value); - - if (w != getWinWidth(app)) - setSaneWinSize(app, w, getWinHeight(app)); -} - - -/* GCONF CALLBACK: Sets window height upon change */ -static void confWinHeight(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int h = gconf_value_get_int(e->value); - - if (h != getWinHeight(app)) - setSaneWinSize(app, getWinWidth(app), h); -} - - -/* GCONF CALLBACK: Sets window X position upon change */ -static void confWinX(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int x = gconf_value_get_int(e->value); - - if (x != getWinX(app)) - setSaneWinPosition(app, x, getWinY(app)); -} - - -/* GCONF CALLBACK: Sets window Y position upon change */ -static void confWinY(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int y = gconf_value_get_int(e->value); - - if (y != getWinY(app)) - setSaneWinPosition(app, getWinX(app), y); -} - - -/* GCONF CALLBACK: Reloads ambient light setting upon change */ -static void confAmbientLight(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - float value = gconf_value_get_float(e->value); - - /* Comparing floats is tricky. Three decimal places is "close enough." */ - if (abs(value - app->renderer->getAmbientLightLevel()) < 0.001) - return; - - setSaneAmbientLight(app, value); -} - - -/* GCONF CALLBACK: Reloads visual magnitude setting upon change */ -static void confVisualMagnitude(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - float value = gconf_value_get_float(e->value); - - if (abs(value - app->simulation->getFaintestVisible()) < 0.001) - return; - - setSaneVisualMagnitude(app, value); -} - - -/* GCONF CALLBACK: Reloads galaxy light gain setting upon change */ -static void confGalaxyLightGain(GConfClient*, guint, GConfEntry* e, AppData*) -{ - float value = gconf_value_get_float(e->value); - - if (abs(value - Galaxy::getLightGain()) < 0.001) - return; - - setSaneGalaxyLightGain(value); -} - - -/* GCONF CALLBACK: Sets texture resolution when changed */ -static void confDistanceLimit(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int value = gconf_value_get_int(e->value); - - if (value == app->renderer->getDistanceLimit()) - return; - - setSaneDistanceLimit(app, value); -} - - -/* GCONF CALLBACK: Sets "show local time" setting upon change */ -static void confShowLocalTime(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - gboolean value = gconf_value_get_bool(e->value); - - if (value == app->showLocalTime) - return; - - app->showLocalTime = value; - updateTimeZone(app, app->showLocalTime); -} - - -/* GCONF CALLBACK: Sets HUD detail when changed */ -static void confVerbosity(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int value = gconf_value_get_int(e->value); - - if (value == app->core->getHudDetail()) - return; - - setSaneVerbosity(app, value); -} - - -/* GCONF CALLBACK: Sets window to fullscreen when change occurs */ -static void confFullScreen(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - gboolean value = gconf_value_get_bool(e->value); - - /* There is no way to determine if the window is actually full screen */ - if (value == app->fullScreen) - return; - - /* The Action handler for full-screen toggles for us, so we set it opposite - * of what is wanted, and... */ - app->fullScreen = !value; - - /* ... tickle it. */ - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(app->agMain, "FullScreen")), value); -} - - -/* GCONF CALLBACK: Sets star style when changed */ -static void confStarStyle(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int value = gconf_value_get_int(e->value); - - if (value == app->renderer->getStarStyle()) - return; - - setSaneStarStyle(app, (Renderer::StarStyle)value); -} - - -/* GCONF CALLBACK: Sets texture resolution when changed */ -static void confTextureResolution(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - int value = gconf_value_get_int(e->value); - - if (value == (int)app->renderer->getResolution()) - return; - - setSaneTextureResolution(app, value); -} - - -/* GCONF CALLBACK: Sets alternate surface texture when changed */ -static void confAltSurfaceName(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - const char* value = gconf_value_get_string(e->value); - - if (string(value) == app->simulation->getActiveObserver()->getDisplayedSurface()) - return; - - setSaneAltSurface(app, (char*)value); -} - - -/* GCONF CALLBACK: Sets video framerate sync when changed */ -static void confVideoSync(GConfClient*, guint, GConfEntry* e, AppData* app) -{ - gboolean value = gconf_value_get_bool(e->value); - - if (value == app->renderer->getVideoSync()) - return; - - app->renderer->setVideoSync(value); -} - - -/* HELPER: Reads in GConf->Render preferences and returns as int mask */ -static int readGConfRender(GConfClient* client) -{ - int rf = Renderer::ShowNothing; - rf |= Renderer::ShowStars * gconf_client_get_bool(client, "/apps/celestia/render/stars", NULL); - rf |= Renderer::ShowPlanets * gconf_client_get_bool(client, "/apps/celestia/render/planets", NULL); - rf |= Renderer::ShowGalaxies * gconf_client_get_bool(client, "/apps/celestia/render/galaxies", NULL); - rf |= Renderer::ShowDiagrams * gconf_client_get_bool(client, "/apps/celestia/render/diagrams", NULL); - rf |= Renderer::ShowCloudMaps * gconf_client_get_bool(client, "/apps/celestia/render/cloudMaps", NULL); - rf |= Renderer::ShowOrbits * gconf_client_get_bool(client, "/apps/celestia/render/orbits", NULL); - rf |= Renderer::ShowCelestialSphere * gconf_client_get_bool(client, "/apps/celestia/render/celestialSphere", NULL); - rf |= Renderer::ShowNightMaps * gconf_client_get_bool(client, "/apps/celestia/render/nightMaps", NULL); - rf |= Renderer::ShowAtmospheres * gconf_client_get_bool(client, "/apps/celestia/render/atmospheres", NULL); - rf |= Renderer::ShowSmoothLines * gconf_client_get_bool(client, "/apps/celestia/render/smoothLines", NULL); - rf |= Renderer::ShowEclipseShadows * gconf_client_get_bool(client, "/apps/celestia/render/eclipseShadows", NULL); - rf |= Renderer::ShowRingShadows * gconf_client_get_bool(client, "/apps/celestia/render/ringShadows", NULL); - rf |= Renderer::ShowBoundaries * gconf_client_get_bool(client, "/apps/celestia/render/boundaries", NULL); - rf |= Renderer::ShowAutoMag * gconf_client_get_bool(client, "/apps/celestia/render/autoMag", NULL); - rf |= Renderer::ShowCometTails * gconf_client_get_bool(client, "/apps/celestia/render/cometTails", NULL); - rf |= Renderer::ShowMarkers * gconf_client_get_bool(client, "/apps/celestia/render/markers", NULL); - rf |= Renderer::ShowPartialTrajectories * gconf_client_get_bool(client, "/apps/celestia/render/partialTrajectories", NULL); - rf |= Renderer::ShowNebulae * gconf_client_get_bool(client, "/apps/celestia/render/nebulae", NULL); - rf |= Renderer::ShowOpenClusters * gconf_client_get_bool(client, "/apps/celestia/render/openClusters", NULL); - rf |= Renderer::ShowGlobulars * gconf_client_get_bool(client, "/apps/celestia/render/globulars", NULL); - rf |= Renderer::ShowGalacticGrid * gconf_client_get_bool(client, "/apps/celestia/render/gridGalactic", NULL); - rf |= Renderer::ShowEclipticGrid * gconf_client_get_bool(client, "/apps/celestia/render/gridEcliptic", NULL); - rf |= Renderer::ShowHorizonGrid * gconf_client_get_bool(client, "/apps/celestia/render/gridHorizontal", NULL); - - return rf; -} - - -/* HELPER: Reads in GConf->Orbits preferences and returns as int mask */ -static int readGConfOrbits(GConfClient* client) -{ - int om = 0; - om |= Body::Planet * gconf_client_get_bool(client, "/apps/celestia/orbits/planet", NULL); - om |= Body::Moon * gconf_client_get_bool(client, "/apps/celestia/orbits/moon", NULL); - om |= Body::Asteroid * gconf_client_get_bool(client, "/apps/celestia/orbits/asteroid", NULL); - om |= Body::Comet * gconf_client_get_bool(client, "/apps/celestia/orbits/comet", NULL); - om |= Body::Spacecraft * gconf_client_get_bool(client, "/apps/celestia/orbits/spacecraft", NULL); - om |= Body::Invisible * gconf_client_get_bool(client, "/apps/celestia/orbits/invisible", NULL); - om |= Body::Unknown * gconf_client_get_bool(client, "/apps/celestia/orbits/unknown", NULL); - - return om; -} - - -/* HELPER: Reads in GConf->Labels preferences and returns as int mask */ -static int readGConfLabels(GConfClient* client) -{ - int lm = Renderer::NoLabels; - lm |= Renderer::StarLabels * gconf_client_get_bool(client, "/apps/celestia/labels/star", NULL); - lm |= Renderer::PlanetLabels * gconf_client_get_bool(client, "/apps/celestia/labels/planet", NULL); - lm |= Renderer::MoonLabels * gconf_client_get_bool(client, "/apps/celestia/labels/moon", NULL); - lm |= Renderer::ConstellationLabels * gconf_client_get_bool(client, "/apps/celestia/labels/constellation", NULL); - lm |= Renderer::GalaxyLabels * gconf_client_get_bool(client, "/apps/celestia/labels/galaxy", NULL); - lm |= Renderer::AsteroidLabels * gconf_client_get_bool(client, "/apps/celestia/labels/asteroid", NULL); - lm |= Renderer::SpacecraftLabels * gconf_client_get_bool(client, "/apps/celestia/labels/spacecraft", NULL); - lm |= Renderer::LocationLabels * gconf_client_get_bool(client, "/apps/celestia/labels/location", NULL); - lm |= Renderer::CometLabels * gconf_client_get_bool(client, "/apps/celestia/labels/comet", NULL); - lm |= Renderer::NebulaLabels * gconf_client_get_bool(client, "/apps/celestia/labels/nebula", NULL); - lm |= Renderer::OpenClusterLabels * gconf_client_get_bool(client, "/apps/celestia/labels/openCluster", NULL); - lm |= Renderer::I18nConstellationLabels * gconf_client_get_bool(client, "/apps/celestia/labels/i18n", NULL); - lm |= Renderer::GlobularLabels * gconf_client_get_bool(client, "/apps/celestia/labels/globular", NULL); - - return lm; -} - - -/* HELPER: Sets one of the flags according to provided type, key, and value */ -static void gcSetFlag(int type, const char* name, gboolean value, GConfClient* client) -{ - gchar key[60]; - switch (type) - { - case Render: sprintf(key, "%s%s", "/apps/celestia/render/", name); break; - case Orbit: sprintf(key, "%s%s", "/apps/celestia/orbits/", name); break; - case Label: sprintf(key, "%s%s", "/apps/celestia/labels/", name); break; - } - - gconf_client_set_bool(client, key, value, NULL); -} diff --git a/src/celestia/gtk/settings-gconf.h b/src/celestia/gtk/settings-gconf.h deleted file mode 100644 index 9dbe27889a..0000000000 --- a/src/celestia/gtk/settings-gconf.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Celestia GTK+ Front-End - * Copyright (C) 2005 Pat Suwalski - * - * This program 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. - * - * $Id: settings-gconf.h,v 1.1 2005-12-06 03:19:36 suwalski Exp $ - */ - -#pragma once - -#include - -#include "common.h" - - -/* Initialize GConf */ -void initSettingsGConf(AppData* app); -void initSettingsGConfNotifiers(AppData* app); - -/* Apply Settings */ -void applySettingsGConfPre(AppData* app, GConfClient* client); -void applySettingsGConfMain(AppData* app, GConfClient* client); - -/* Save Settings to GConf */ -void saveSettingsGConf(AppData* app); - -/* Utility Functions */ -void gcSetRenderFlag(int flag, gboolean state, GConfClient* client); -void gcSetOrbitMask(int flag, gboolean state, GConfClient* client); -void gcSetLabelMode(int flag, gboolean state, GConfClient* client); - - -enum { - Render = 0, - Orbit = 1, - Label = 2, -}; diff --git a/src/celestia/gtk/splash.cpp b/src/celestia/gtk/splash.cpp index 28502b85a8..2fefd2a602 100644 --- a/src/celestia/gtk/splash.cpp +++ b/src/celestia/gtk/splash.cpp @@ -10,6 +10,8 @@ * $Id: splash.cpp,v 1.4 2006-07-24 17:31:24 christey Exp $ */ +#include + #include #include #include @@ -21,28 +23,90 @@ #include "splash.h" #include "common.h" -using namespace std; +namespace celestia::gtk +{ +namespace +{ /* Declarations */ #if GTK_MAJOR_VERSION == 2 -static gboolean splashExpose(GtkWidget* win, GdkEventExpose *event, SplashData* ss); -#endif +/* CALLBACK: Called when the splash screen is exposed */ +gboolean +splashExpose(GtkWidget* win, GdkEventExpose *event, SplashData* ss) +{ + /* All of this code is only needed at the very first drawing. This + * operation is quite expensive. */ + if (ss->redraw != TRUE) return FALSE; + + GdkWindow *ww = gtk_widget_get_window(win); + + if (ss->hasARGB) + { + #ifdef CAIRO + /* Use cairo for true transparent windows */ + cairo_t *cr = gdk_cairo_create(ww); + + cairo_rectangle(cr, event->area.x, + event->area.y, + event->area.width, + event->area.height); + cairo_clip(cr); + + /* Draw a fully transparent rectangle the size of the window */ + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0); + + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_destroy(cr); + #endif /* CAIRO */ + } + else + { + /* Fall back to compositing a screenshot of whatever is below the + * area we are drawing in. */ + GdkPixbuf* bg; + int x, y, w, h; + + gdk_window_get_root_origin(ww, &x, &y); + w = gdk_window_get_width(ww); + h = gdk_window_get_height(ww); + + bg = gdk_pixbuf_get_from_drawable(nullptr, + gtk_widget_get_root_window(win), + nullptr, x, y, 0, 0, w, h); + cairo_t *cr = gdk_cairo_create(ww); + gdk_cairo_set_source_pixbuf(cr, bg, x, y); + cairo_paint(cr); + cairo_destroy(cr); + g_object_unref(bg); + } + + /* Never redraw again */ + ss->redraw = FALSE; + + return FALSE; +} +#endif +} // end unnamed namespace /* OBJECT: Overrides ProgressNotifier to receive feedback from core */ GtkSplashProgressNotifier::GtkSplashProgressNotifier(SplashData* _splash) : - splash(_splash) {}; + splash(_splash) +{ +}; -void GtkSplashProgressNotifier::update(const string& filename) +void +GtkSplashProgressNotifier::update(const std::string& filename) { splashSetText(splash, filename.c_str()); } GtkSplashProgressNotifier::~GtkSplashProgressNotifier() {}; - /* ENTRY: Creates a new SplashData struct, starts the splash screen */ -SplashData* splashStart(AppData* app, gboolean showSplash, const gchar* installDir, const gchar* defaultDir) +SplashData* +splashStart(AppData* app, gboolean showSplash, const gchar* installDir, const gchar* defaultDir) { SplashData* ss = g_new0(SplashData, 1); @@ -65,7 +129,7 @@ SplashData* splashStart(AppData* app, gboolean showSplash, const gchar* installD /* Colormap Magic */ GdkScreen* screen = gtk_widget_get_screen(ss->splash); GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen); - if (colormap != NULL) + if (colormap != nullptr) { gtk_widget_set_colormap(ss->splash, colormap); ss->hasARGB = TRUE; @@ -97,7 +161,7 @@ SplashData* splashStart(AppData* app, gboolean showSplash, const gchar* installD /* The information label is right-aligned and biased to the lower-right * of the window. It's designed to be the full width and height of the * opaque parts of the splash. */ - ss->label = gtk_label_new(NULL); + ss->label = gtk_label_new(nullptr); gtk_misc_set_alignment(GTK_MISC(ss->label), 1, 1); gtk_label_set_justify(GTK_LABEL(ss->label), GTK_JUSTIFY_RIGHT); gtk_widget_modify_fg(ss->label, GTK_STATE_NORMAL, >k_widget_get_style(ss->label)->white); @@ -123,9 +187,9 @@ SplashData* splashStart(AppData* app, gboolean showSplash, const gchar* installD return ss; } - /* ENTRY: destroys the splash screen */ -void splashEnd(SplashData* ss) +void +splashEnd(SplashData* ss) { if (ss->splash) gtk_widget_destroy(ss->splash); @@ -137,16 +201,16 @@ void splashEnd(SplashData* ss) g_free(ss); } - /* ENTRY: Sets the text to be shown in the splash */ -void splashSetText(SplashData* ss, const char* text) +void +splashSetText(SplashData* ss, const char* text) { char message[255]; if (!ss->splash) return; - sprintf(message, "Version " VERSION "\n%s", text); + std::sprintf(message, "Version " VERSION "\n%s", text); gtk_label_set_text(GTK_LABEL(ss->label), message); @@ -154,61 +218,4 @@ void splashSetText(SplashData* ss, const char* text) while (gtk_events_pending()) gtk_main_iteration(); } -#if GTK_MAJOR_VERSION == 2 -/* CALLBACK: Called when the splash screen is exposed */ -static gboolean splashExpose(GtkWidget* win, GdkEventExpose *event, SplashData* ss) -{ - /* All of this code is only needed at the very first drawing. This - * operation is quite expensive. */ - if (ss->redraw != TRUE) return FALSE; - - GdkWindow *ww = gtk_widget_get_window(win); - - if (ss->hasARGB) - { - #ifdef CAIRO - /* Use cairo for true transparent windows */ - cairo_t *cr = gdk_cairo_create(ww); - - cairo_rectangle(cr, event->area.x, - event->area.y, - event->area.width, - event->area.height); - cairo_clip(cr); - - /* Draw a fully transparent rectangle the size of the window */ - cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_paint(cr); - - cairo_destroy(cr); - #endif /* CAIRO */ - } - else - { - /* Fall back to compositing a screenshot of whatever is below the - * area we are drawing in. */ - GdkPixbuf* bg; - int x, y, w, h; - - gdk_window_get_root_origin(ww, &x, &y); - w = gdk_window_get_width(ww); - h = gdk_window_get_height(ww); - - bg = gdk_pixbuf_get_from_drawable(NULL, - gtk_widget_get_root_window(win), - NULL, x, y, 0, 0, w, h); - cairo_t *cr = gdk_cairo_create(ww); - gdk_cairo_set_source_pixbuf(cr, bg, x, y); - cairo_paint(cr); - cairo_destroy(cr); - g_object_unref(bg); - } - - /* Never redraw again */ - ss->redraw = FALSE; - - return FALSE; -} -#endif +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/splash.h b/src/celestia/gtk/splash.h index 5c01876a7d..7820297d7f 100644 --- a/src/celestia/gtk/splash.h +++ b/src/celestia/gtk/splash.h @@ -12,27 +12,19 @@ #pragma once +#include + #include "common.h" #include -typedef struct _SplashData SplashData; - -/* This class overrides the ProgressNotifier to receive splash event updates - * from the core. */ -class GtkSplashProgressNotifier : public ProgressNotifier +namespace celestia::gtk { - public: - GtkSplashProgressNotifier(SplashData* _splash); - virtual ~GtkSplashProgressNotifier(); - virtual void update(const std::string& filename); - - private: - SplashData* splash; -}; +class GtkSplashProgressNotifier; /* Struct holds all information relevant to the splash screen. */ +typedef struct _SplashData SplashData; struct _SplashData { AppData* app; @@ -45,8 +37,23 @@ struct _SplashData { gboolean redraw; }; +/* This class overrides the ProgressNotifier to receive splash event updates + * from the core. */ +class GtkSplashProgressNotifier : public ProgressNotifier +{ + public: + GtkSplashProgressNotifier(SplashData* _splash); + virtual ~GtkSplashProgressNotifier(); + + virtual void update(const std::string& filename); + + private: + SplashData* splash; +}; /* Entry Functions */ SplashData* splashStart(AppData* app, gboolean showSplash, const gchar* installDir, const gchar* defaultDir); void splashEnd(SplashData* ss); void splashSetText(SplashData* ss, const char* text); + +} // end namespace celestia::gtk diff --git a/src/celestia/gtk/ui.h b/src/celestia/gtk/ui.h index 7fef471d15..192093f225 100644 --- a/src/celestia/gtk/ui.h +++ b/src/celestia/gtk/ui.h @@ -12,182 +12,193 @@ #pragma once +#include + #include #include "actions.h" +namespace celestia::gtk +{ + /* By default all action widgets are turned off. They will be set later when * they are being synchronized with settings and with the core. */ /* Regular Actions */ -static const GtkActionEntry actionsPlain[] = { - { "FileMenu", NULL, "_File", NULL, NULL, NULL }, - { "CopyURL", GTK_STOCK_COPY, "Copy _URL", NULL, NULL, G_CALLBACK(actionCopyURL) }, - { "OpenURL", NULL, "Open UR_L", NULL, NULL, G_CALLBACK(actionOpenURL) }, - { "OpenScript", GTK_STOCK_OPEN, "_Open Script...", NULL, NULL, G_CALLBACK(actionOpenScript) }, - { "CaptureImage", GTK_STOCK_SAVE_AS, "_Capture Image...", NULL, NULL, G_CALLBACK(actionCaptureImage) }, - { "CaptureMovie", GTK_STOCK_SAVE_AS, "Capture _Movie...", NULL, NULL, G_CALLBACK(actionCaptureMovie) }, - { "RunDemo", GTK_STOCK_EXECUTE, "Run _Demo", NULL, NULL, G_CALLBACK(actionRunDemo) }, - { "Quit", GTK_STOCK_QUIT, "_Quit", "Q", NULL, G_CALLBACK(actionQuit) }, - - { "NavigationMenu", NULL, "_Navigation", NULL, NULL, NULL }, - { "SelectSol", GTK_STOCK_HOME, "Select _Sol", "H", NULL, G_CALLBACK(actionSelectSol) }, - { "TourGuide", NULL, "Tour G_uide...", NULL, NULL, G_CALLBACK(actionTourGuide) }, - { "SearchObject", GTK_STOCK_FIND, "Search for _Object...", NULL, NULL, G_CALLBACK(actionSearchObject) }, - { "GotoObject", NULL, "Go to Object...", NULL, NULL, G_CALLBACK(actionGotoObject) }, - { "CenterSelection", NULL, "_Center Selection", "c", NULL, G_CALLBACK(actionCenterSelection) }, - { "GotoSelection", GTK_STOCK_JUMP_TO, "_Go to Selection", "G", NULL, G_CALLBACK(actionGotoSelection) }, - { "FollowSelection", NULL, "_Follow Selection", "F", NULL, G_CALLBACK(actionFollowSelection) }, - { "SyncSelection", NULL, "S_ync Orbit Selection", "Y", NULL, G_CALLBACK(actionSyncSelection) }, - { "TrackSelection", NULL, "_Track Selection", "T", NULL, G_CALLBACK(actionTrackSelection) }, - { "SystemBrowser", NULL, "Solar System _Browser...", NULL, NULL, G_CALLBACK(actionSystemBrowser) }, - { "StarBrowser", NULL, "Star B_rowser...", NULL, NULL, G_CALLBACK(actionStarBrowser) }, - { "EclipseFinder", NULL, "_Eclipse Finder...", NULL, NULL, G_CALLBACK(actionEclipseFinder) }, - - { "TimeMenu", NULL, "_Time", NULL, NULL, NULL }, - { "TimeFaster", NULL, "2x _Faster", "L", NULL, G_CALLBACK(actionTimeFaster) }, - { "TimeSlower", NULL, "2x _Slower", "K", NULL, G_CALLBACK(actionTimeSlower) }, - { "TimeFreeze", NULL, "Free_ze", "space", NULL, G_CALLBACK(actionTimeFreeze) }, - { "TimeReal", NULL, "_Real Time", "backslash", NULL, G_CALLBACK(actionTimeReal) }, - { "TimeReverse", NULL, "Re_verse Time", "J", NULL, G_CALLBACK(actionTimeReverse) }, - { "TimeSet", NULL, "Set _Time...", NULL, NULL, G_CALLBACK(actionTimeSet) }, +const inline std::array actionsPlain +{ + GtkActionEntry{ "FileMenu", nullptr, "_File", nullptr, nullptr, nullptr }, + GtkActionEntry{ "CopyURL", GTK_STOCK_COPY, "Copy _URL", nullptr, nullptr, G_CALLBACK(actionCopyURL) }, + GtkActionEntry{ "OpenURL", nullptr, "Open UR_L", nullptr, nullptr, G_CALLBACK(actionOpenURL) }, + GtkActionEntry{ "OpenScript", GTK_STOCK_OPEN, "_Open Script...", nullptr, nullptr, G_CALLBACK(actionOpenScript) }, + GtkActionEntry{ "CaptureImage", GTK_STOCK_SAVE_AS, "_Capture Image...", nullptr, nullptr, G_CALLBACK(actionCaptureImage) }, + GtkActionEntry{ "CaptureMovie", GTK_STOCK_SAVE_AS, "Capture _Movie...", nullptr, nullptr, G_CALLBACK(actionCaptureMovie) }, + GtkActionEntry{ "RunDemo", GTK_STOCK_EXECUTE, "Run _Demo", nullptr, nullptr, G_CALLBACK(actionRunDemo) }, + GtkActionEntry{ "Quit", GTK_STOCK_QUIT, "_Quit", "Q", nullptr, G_CALLBACK(actionQuit) }, + + GtkActionEntry{ "NavigationMenu", nullptr, "_Navigation", nullptr, nullptr, nullptr }, + GtkActionEntry{ "SelectSol", GTK_STOCK_HOME, "Select _Sol", "H", nullptr, G_CALLBACK(actionSelectSol) }, + GtkActionEntry{ "TourGuide", nullptr, "Tour G_uide...", nullptr, nullptr, G_CALLBACK(actionTourGuide) }, + GtkActionEntry{ "SearchObject", GTK_STOCK_FIND, "Search for _Object...", nullptr, nullptr, G_CALLBACK(actionSearchObject) }, + GtkActionEntry{ "GotoObject", nullptr, "Go to Object...", nullptr, nullptr, G_CALLBACK(actionGotoObject) }, + GtkActionEntry{ "CenterSelection", nullptr, "_Center Selection", "c", nullptr, G_CALLBACK(actionCenterSelection) }, + GtkActionEntry{ "GotoSelection", GTK_STOCK_JUMP_TO, "_Go to Selection", "G", nullptr, G_CALLBACK(actionGotoSelection) }, + GtkActionEntry{ "FollowSelection", nullptr, "_Follow Selection", "F", nullptr, G_CALLBACK(actionFollowSelection) }, + GtkActionEntry{ "SyncSelection", nullptr, "S_ync Orbit Selection", "Y", nullptr, G_CALLBACK(actionSyncSelection) }, + GtkActionEntry{ "TrackSelection", nullptr, "_Track Selection", "T", nullptr, G_CALLBACK(actionTrackSelection) }, + GtkActionEntry{ "SystemBrowser", nullptr, "Solar System _Browser...", nullptr, nullptr, G_CALLBACK(actionSystemBrowser) }, + GtkActionEntry{ "StarBrowser", nullptr, "Star B_rowser...", nullptr, nullptr, G_CALLBACK(actionStarBrowser) }, + GtkActionEntry{ "EclipseFinder", nullptr, "_Eclipse Finder...", nullptr, nullptr, G_CALLBACK(actionEclipseFinder) }, + + GtkActionEntry{ "TimeMenu", nullptr, "_Time", nullptr, nullptr, nullptr }, + GtkActionEntry{ "TimeFaster", nullptr, "2x _Faster", "L", nullptr, G_CALLBACK(actionTimeFaster) }, + GtkActionEntry{ "TimeSlower", nullptr, "2x _Slower", "K", nullptr, G_CALLBACK(actionTimeSlower) }, + GtkActionEntry{ "TimeFreeze", nullptr, "Free_ze", "space", nullptr, G_CALLBACK(actionTimeFreeze) }, + GtkActionEntry{ "TimeReal", nullptr, "_Real Time", "backslash", nullptr, G_CALLBACK(actionTimeReal) }, + GtkActionEntry{ "TimeReverse", nullptr, "Re_verse Time", "J", nullptr, G_CALLBACK(actionTimeReverse) }, + GtkActionEntry{ "TimeSet", nullptr, "Set _Time...", nullptr, nullptr, G_CALLBACK(actionTimeSet) }, /* "Show Local Time" in toggle actions */ - { "OptionsMenu", NULL, "_Options", NULL, NULL, NULL }, - { "ViewOptions", GTK_STOCK_PREFERENCES, "View _Options...", NULL, NULL, G_CALLBACK(actionViewOptions) }, - { "ShowObjectsMenu", NULL, "Show Objects", NULL, NULL, NULL }, - { "ShowGridsMenu", NULL, "Show Grids", NULL, NULL, NULL }, - { "ShowLabelsMenu", NULL, "Show Labels", NULL, NULL, NULL }, - { "ShowOrbitsMenu", NULL, "Show Orbits", NULL, NULL, NULL }, - { "InfoTextMenu", NULL, "Info Text", NULL, NULL, NULL }, - /* "Info Text" in radio actions */ - { "StarStyleMenu", NULL, "Star St_yle", NULL, NULL, NULL }, - /* "Star Style" in radio actions */ - { "AmbientLightMenu", NULL, "_Ambient Light", NULL, NULL, NULL }, - /* "Ambient Light" in radio actions */ - { "StarsMore", NULL, "_More Stars Visible", "bracketright", NULL, G_CALLBACK(actionStarsMore) }, - { "StarsFewer", NULL, "_Fewer Stars Visible", "bracketleft", NULL, G_CALLBACK(actionStarsFewer) }, - - { "WindowMenu", NULL, "_Window", NULL, NULL, NULL }, - { "ViewerSize", GTK_STOCK_ZOOM_FIT, "Set Window Size...", NULL, NULL, G_CALLBACK(actionViewerSize) }, + GtkActionEntry{ "OptionsMenu", nullptr, "_Options", nullptr, nullptr, nullptr }, + GtkActionEntry{ "ViewOptions", GTK_STOCK_PREFERENCES, "View _Options...", nullptr, nullptr, G_CALLBACK(actionViewOptions) }, + GtkActionEntry{ "ShowObjectsMenu", nullptr, "Show Objects", nullptr, nullptr, nullptr }, + GtkActionEntry{ "ShowGridsMenu", nullptr, "Show Grids", nullptr, nullptr, nullptr }, + GtkActionEntry{ "ShowLabelsMenu", nullptr, "Show Labels", nullptr, nullptr, nullptr }, + GtkActionEntry{ "ShowOrbitsMenu", nullptr, "Show Orbits", nullptr, nullptr, nullptr }, + GtkActionEntry{ "InfoTextMenu", nullptr, "Info Text", nullptr, nullptr, nullptr }, + /* "Info Text" in radio actions */ + GtkActionEntry{ "StarStyleMenu", nullptr, "Star St_yle", nullptr, nullptr, nullptr }, + /* "Star Style" in radio actions */ + GtkActionEntry{ "AmbientLightMenu", nullptr, "_Ambient Light", nullptr, nullptr, nullptr }, + /* "Ambient Light" in radio actions */ + GtkActionEntry{ "StarsMore", nullptr, "_More Stars Visible", "bracketright", nullptr, G_CALLBACK(actionStarsMore) }, + GtkActionEntry{ "StarsFewer", nullptr, "_Fewer Stars Visible", "bracketleft", nullptr, G_CALLBACK(actionStarsFewer) }, + + GtkActionEntry{ "WindowMenu", nullptr, "_Window", nullptr, nullptr, nullptr }, + GtkActionEntry{ "ViewerSize", GTK_STOCK_ZOOM_FIT, "Set Window Size...", nullptr, nullptr, G_CALLBACK(actionViewerSize) }, /* "Full Screen" in toggle actions */ - { "MultiSplitH", NULL, "Split _Horizontally", "R", NULL, G_CALLBACK(actionMultiSplitH) }, - { "MultiSplitV", NULL, "Split _Vertically", "U", NULL, G_CALLBACK(actionMultiSplitV) }, - { "MultiCycle", NULL, "Cycle View", "Tab", NULL, G_CALLBACK(actionMultiCycle) }, - { "MultiDelete", NULL, "_Delete Active View", "Delete", NULL, G_CALLBACK(actionMultiDelete) }, - { "MultiSingle", NULL, "_Single View", "D", NULL, G_CALLBACK(actionMultiSingle) }, + GtkActionEntry{ "MultiSplitH", nullptr, "Split _Horizontally", "R", nullptr, G_CALLBACK(actionMultiSplitH) }, + GtkActionEntry{ "MultiSplitV", nullptr, "Split _Vertically", "U", nullptr, G_CALLBACK(actionMultiSplitV) }, + GtkActionEntry{ "MultiCycle", nullptr, "Cycle View", "Tab", nullptr, G_CALLBACK(actionMultiCycle) }, + GtkActionEntry{ "MultiDelete", nullptr, "_Delete Active View", "Delete", nullptr, G_CALLBACK(actionMultiDelete) }, + GtkActionEntry{ "MultiSingle", nullptr, "_Single View", "D", nullptr, G_CALLBACK(actionMultiSingle) }, /* "Show Frames" in toggle actions */ /* "Synchronize Time" in toggle actions */ - { "HelpMenu", NULL, "_Help", NULL, NULL, NULL }, - { "HelpControls", GTK_STOCK_HELP, "_Controls", NULL, NULL, G_CALLBACK(actionHelpControls) }, + GtkActionEntry{ "HelpMenu", nullptr, "_Help", nullptr, nullptr, nullptr }, + GtkActionEntry{ "HelpControls", GTK_STOCK_HELP, "_Controls", nullptr, nullptr, G_CALLBACK(actionHelpControls) }, #if GTK_CHECK_VERSION(2, 7, 0) - { "HelpOpenGL", GTK_STOCK_INFO, "OpenGL _Info", NULL, NULL, G_CALLBACK(actionHelpOpenGL) }, + GtkActionEntry{ "HelpOpenGL", GTK_STOCK_INFO, "OpenGL _Info", nullptr, nullptr, G_CALLBACK(actionHelpOpenGL) }, #else - { "HelpOpenGL", NULL, "OpenGL _Info", NULL, NULL, G_CALLBACK(actionHelpOpenGL) }, + GtkActionEntry{ "HelpOpenGL", nullptr, "OpenGL _Info", nullptr, nullptr, G_CALLBACK(actionHelpOpenGL) }, #endif - { "HelpAbout", GTK_STOCK_ABOUT, "_About", NULL, NULL, G_CALLBACK(actionHelpAbout) }, + GtkActionEntry{ "HelpAbout", GTK_STOCK_ABOUT, "_About", nullptr, nullptr, G_CALLBACK(actionHelpAbout) }, }; - /* Regular Checkbox Actions */ -static const GtkToggleActionEntry actionsToggle[] = { - { "TimeLocal", NULL, "Show _Local Time", NULL, NULL, G_CALLBACK(actionTimeLocal), FALSE }, +const inline std::array actionsToggle +{ + GtkToggleActionEntry{ "TimeLocal", nullptr, "Show _Local Time", nullptr, nullptr, G_CALLBACK(actionTimeLocal), FALSE }, #if GTK_CHECK_VERSION(2, 7, 0) - { "FullScreen", GTK_STOCK_FULLSCREEN, "_Full Screen", "Return", NULL, G_CALLBACK(actionFullScreen), FALSE }, + GtkToggleActionEntry{ "FullScreen", GTK_STOCK_FULLSCREEN, "_Full Screen", "Return", nullptr, G_CALLBACK(actionFullScreen), FALSE }, #else - { "FullScreen", NULL, "_Full Screen", "Return", NULL, G_CALLBACK(actionFullScreen), FALSE }, + GtkToggleActionEntry{ "FullScreen", nullptr, "_Full Screen", "Return", nullptr, G_CALLBACK(actionFullScreen), FALSE }, #endif /* GTK_CHECK_VERSION */ - { "MenuBarVisible", NULL, "_Menu Bar", "M", NULL, G_CALLBACK(actionMenuBarVisible), TRUE }, - { "MultiShowFrames", NULL, "Show _Frames", NULL, NULL, G_CALLBACK(actionMultiShowFrames), FALSE }, - { "MultiShowActive", NULL, "Active Frame Highlighted", NULL, NULL, G_CALLBACK(actionMultiShowActive), FALSE }, - { "MultiSyncTime", NULL, "Synchronize _Time", NULL, NULL, G_CALLBACK(actionMultiSyncTime), FALSE }, + GtkToggleActionEntry{ "MenuBarVisible", nullptr, "_Menu Bar", "M", nullptr, G_CALLBACK(actionMenuBarVisible), TRUE }, + GtkToggleActionEntry{ "MultiShowFrames", nullptr, "Show _Frames", nullptr, nullptr, G_CALLBACK(actionMultiShowFrames), FALSE }, + GtkToggleActionEntry{ "MultiShowActive", nullptr, "Active Frame Highlighted", nullptr, nullptr, G_CALLBACK(actionMultiShowActive), FALSE }, + GtkToggleActionEntry{ "MultiSyncTime", nullptr, "Synchronize _Time", nullptr, nullptr, G_CALLBACK(actionMultiSyncTime), FALSE }, }; - /* Regular Radio Button Actions */ -static const GtkRadioActionEntry actionsVerbosity[] = { - { "HudNone", NULL, "_None", NULL, NULL, 0 }, - { "HudTerse", NULL, "_Terse", NULL, NULL, 1}, - { "HudVerbose", NULL, "_Verbose", NULL, NULL, 2}, +constexpr inline std::array actionsVerbosity +{ + GtkRadioActionEntry{ "HudNone", nullptr, "_None", nullptr, nullptr, 0 }, + GtkRadioActionEntry{ "HudTerse", nullptr, "_Terse", nullptr, nullptr, 1}, + GtkRadioActionEntry{ "HudVerbose", nullptr, "_Verbose", nullptr, nullptr, 2}, }; -static const GtkRadioActionEntry actionsStarStyle[] = { - { "StarsFuzzy", NULL, "_Fuzzy Points", NULL, NULL, Renderer::FuzzyPointStars }, - { "StarsPoints", NULL, "_Points", NULL, NULL, Renderer::PointStars }, - { "StarsDiscs", NULL, "Scaled _Discs", NULL, NULL, Renderer::ScaledDiscStars }, +constexpr inline std::array actionsStarStyle +{ + GtkRadioActionEntry{ "StarsFuzzy", nullptr, "_Fuzzy Points", nullptr, nullptr, Renderer::FuzzyPointStars }, + GtkRadioActionEntry{ "StarsPoints", nullptr, "_Points", nullptr, nullptr, Renderer::PointStars }, + GtkRadioActionEntry{ "StarsDiscs", nullptr, "Scaled _Discs", nullptr, nullptr, Renderer::ScaledDiscStars }, }; -static const GtkRadioActionEntry actionsAmbientLight[] = { - { "AmbientNone", NULL, "_None", NULL, NULL, 0 }, - { "AmbientLow", NULL, "_Low", NULL, NULL, 1 }, - { "AmbientMedium", NULL, "_Medium", NULL, NULL, 2}, +constexpr inline std::array actionsAmbientLight +{ + GtkRadioActionEntry{ "AmbientNone", nullptr, "_None", nullptr, nullptr, 0 }, + GtkRadioActionEntry{ "AmbientLow", nullptr, "_Low", nullptr, nullptr, 1 }, + GtkRadioActionEntry{ "AmbientMedium", nullptr, "_Medium", nullptr, nullptr, 2}, }; - /* Render-Flag Actions */ -static const GtkToggleActionEntry actionsRenderFlags[] = { - { "RenderAA", NULL, "Antialiasing", "X", NULL, G_CALLBACK(actionRenderAA), FALSE }, - { "RenderAtmospheres", NULL, "Atmospheres", "A", NULL, G_CALLBACK(actionRenderAtmospheres), FALSE }, - { "RenderAutoMagnitude", NULL, "Auto Magnitude", "Y", NULL, G_CALLBACK(actionRenderAutoMagnitude), FALSE }, - { "RenderClouds", NULL, "Clouds", "I", NULL, G_CALLBACK(actionRenderClouds), FALSE }, - { "RenderCometTails", NULL, "Comet Tails", "T", NULL, G_CALLBACK(actionRenderCometTails), FALSE }, - { "RenderConstellationBoundaries", NULL, "Constellation Boundaries", NULL, NULL, G_CALLBACK(actionRenderConstellationBoundaries), FALSE }, - { "RenderConstellations", NULL, "Constellations", "slash", NULL, G_CALLBACK(actionRenderConstellations), FALSE }, - { "RenderEclipseShadows", NULL, "Eclipse Shadows", "E", NULL, G_CALLBACK(actionRenderEclipseShadows), FALSE }, - { "RenderGalaxies", NULL, "Galaxies", "U", NULL, G_CALLBACK(actionRenderGalaxies), FALSE }, - { "RenderGlobulars", NULL, "Globulars", "U", NULL, G_CALLBACK(actionRenderGlobulars), FALSE }, - { "RenderCelestialGrid", NULL, "Grid: Celestial", "semicolon", NULL, G_CALLBACK(actionRenderCelestialGrid), FALSE }, - { "RenderEclipticGrid", NULL, "Grid: Ecliptic", NULL, NULL, G_CALLBACK(actionRenderEclipticGrid), FALSE }, - { "RenderGalacticGrid", NULL, "Grid: Galactic", NULL, NULL, G_CALLBACK(actionRenderGalacticGrid), FALSE }, - { "RenderHorizontalGrid", NULL, "Grid: Horizontal", NULL, NULL, G_CALLBACK(actionRenderHorizontalGrid), FALSE }, - { "RenderMarkers", NULL, "Markers", "M", NULL, G_CALLBACK(actionRenderMarkers), FALSE }, - { "RenderNebulae", NULL, "Nebulae", "asciicircum", NULL, G_CALLBACK(actionRenderNebulae), FALSE }, - { "RenderNightLights", NULL, "Night Side Lights", "L", NULL, G_CALLBACK(actionRenderNightLights), FALSE }, - { "RenderOpenClusters", NULL, "Open Clusters", NULL, NULL, G_CALLBACK(actionRenderOpenClusters), FALSE }, - { "RenderOrbits", NULL, "Orbits", "O", NULL, G_CALLBACK(actionRenderOrbits), FALSE }, - { "RenderFadingOrbits", NULL, "Fading Orbits", NULL, NULL, G_CALLBACK(actionRenderFadingOrbits), FALSE }, - { "RenderPlanets", NULL, "Planets", NULL, NULL, G_CALLBACK(actionRenderPlanets), FALSE }, - { "RenderDwarfPlanets", NULL, "Dwarf Planets", NULL, NULL, G_CALLBACK(actionRenderDwarfPlanets), FALSE }, - { "RenderMoons", NULL, "Moons", NULL, NULL, G_CALLBACK(actionRenderMoons), FALSE }, - { "RenderMinorMoons", NULL, "Minor Moons", NULL, NULL, G_CALLBACK(actionRenderMinorMoons), FALSE }, - { "RenderComets", NULL, "Comets", NULL, NULL, G_CALLBACK(actionRenderComets), FALSE }, - { "RenderAsteroids", NULL, "Asteroids", NULL, NULL, G_CALLBACK(actionRenderAsteroids), FALSE }, - { "RenderSpacecrafts", NULL, "Spacecraft", NULL, NULL, G_CALLBACK(actionRenderSpacecrafts), FALSE }, - { "RenderPlanetRings", NULL, "Planet Rings", NULL, NULL, G_CALLBACK(actionRenderPlanetRings), FALSE }, - { "RenderRingShadows", NULL, "Ring Shadows", NULL, NULL, G_CALLBACK(actionRenderRingShadows), FALSE }, - { "RenderStars", NULL, "Stars", NULL, NULL, G_CALLBACK(actionRenderStars), FALSE }, +const inline std::array actionsRenderFlags +{ + GtkToggleActionEntry{ "RenderAA", nullptr, "Antialiasing", "X", nullptr, G_CALLBACK(actionRenderAA), FALSE }, + GtkToggleActionEntry{ "RenderAtmospheres", nullptr, "Atmospheres", "A", nullptr, G_CALLBACK(actionRenderAtmospheres), FALSE }, + GtkToggleActionEntry{ "RenderAutoMagnitude", nullptr, "Auto Magnitude", "Y", nullptr, G_CALLBACK(actionRenderAutoMagnitude), FALSE }, + GtkToggleActionEntry{ "RenderClouds", nullptr, "Clouds", "I", nullptr, G_CALLBACK(actionRenderClouds), FALSE }, + GtkToggleActionEntry{ "RenderCometTails", nullptr, "Comet Tails", "T", nullptr, G_CALLBACK(actionRenderCometTails), FALSE }, + GtkToggleActionEntry{ "RenderConstellationBoundaries", nullptr, "Constellation Boundaries", nullptr, nullptr, G_CALLBACK(actionRenderConstellationBoundaries), FALSE }, + GtkToggleActionEntry{ "RenderConstellations", nullptr, "Constellations", "slash", nullptr, G_CALLBACK(actionRenderConstellations), FALSE }, + GtkToggleActionEntry{ "RenderEclipseShadows", nullptr, "Eclipse Shadows", "E", nullptr, G_CALLBACK(actionRenderEclipseShadows), FALSE }, + GtkToggleActionEntry{ "RenderGalaxies", nullptr, "Galaxies", "U", nullptr, G_CALLBACK(actionRenderGalaxies), FALSE }, + GtkToggleActionEntry{ "RenderGlobulars", nullptr, "Globulars", "U", nullptr, G_CALLBACK(actionRenderGlobulars), FALSE }, + GtkToggleActionEntry{ "RenderCelestialGrid", nullptr, "Grid: Celestial", "semicolon", nullptr, G_CALLBACK(actionRenderCelestialGrid), FALSE }, + GtkToggleActionEntry{ "RenderEclipticGrid", nullptr, "Grid: Ecliptic", nullptr, nullptr, G_CALLBACK(actionRenderEclipticGrid), FALSE }, + GtkToggleActionEntry{ "RenderGalacticGrid", nullptr, "Grid: Galactic", nullptr, nullptr, G_CALLBACK(actionRenderGalacticGrid), FALSE }, + GtkToggleActionEntry{ "RenderHorizontalGrid", nullptr, "Grid: Horizontal", nullptr, nullptr, G_CALLBACK(actionRenderHorizontalGrid), FALSE }, + GtkToggleActionEntry{ "RenderMarkers", nullptr, "Markers", "M", nullptr, G_CALLBACK(actionRenderMarkers), FALSE }, + GtkToggleActionEntry{ "RenderNebulae", nullptr, "Nebulae", "asciicircum", nullptr, G_CALLBACK(actionRenderNebulae), FALSE }, + GtkToggleActionEntry{ "RenderNightLights", nullptr, "Night Side Lights", "L", nullptr, G_CALLBACK(actionRenderNightLights), FALSE }, + GtkToggleActionEntry{ "RenderOpenClusters", nullptr, "Open Clusters", nullptr, nullptr, G_CALLBACK(actionRenderOpenClusters), FALSE }, + GtkToggleActionEntry{ "RenderOrbits", nullptr, "Orbits", "O", nullptr, G_CALLBACK(actionRenderOrbits), FALSE }, + GtkToggleActionEntry{ "RenderFadingOrbits", nullptr, "Fading Orbits", nullptr, nullptr, G_CALLBACK(actionRenderFadingOrbits), FALSE }, + GtkToggleActionEntry{ "RenderPlanets", nullptr, "Planets", nullptr, nullptr, G_CALLBACK(actionRenderPlanets), FALSE }, + GtkToggleActionEntry{ "RenderDwarfPlanets", nullptr, "Dwarf Planets", nullptr, nullptr, G_CALLBACK(actionRenderDwarfPlanets), FALSE }, + GtkToggleActionEntry{ "RenderMoons", nullptr, "Moons", nullptr, nullptr, G_CALLBACK(actionRenderMoons), FALSE }, + GtkToggleActionEntry{ "RenderMinorMoons", nullptr, "Minor Moons", nullptr, nullptr, G_CALLBACK(actionRenderMinorMoons), FALSE }, + GtkToggleActionEntry{ "RenderComets", nullptr, "Comets", nullptr, nullptr, G_CALLBACK(actionRenderComets), FALSE }, + GtkToggleActionEntry{ "RenderAsteroids", nullptr, "Asteroids", nullptr, nullptr, G_CALLBACK(actionRenderAsteroids), FALSE }, + GtkToggleActionEntry{ "RenderSpacecrafts", nullptr, "Spacecraft", nullptr, nullptr, G_CALLBACK(actionRenderSpacecrafts), FALSE }, + GtkToggleActionEntry{ "RenderPlanetRings", nullptr, "Planet Rings", nullptr, nullptr, G_CALLBACK(actionRenderPlanetRings), FALSE }, + GtkToggleActionEntry{ "RenderRingShadows", nullptr, "Ring Shadows", nullptr, nullptr, G_CALLBACK(actionRenderRingShadows), FALSE }, + GtkToggleActionEntry{ "RenderStars", nullptr, "Stars", nullptr, nullptr, G_CALLBACK(actionRenderStars), FALSE }, }; - /* Orbit-Flag Actions */ -static const GtkToggleActionEntry actionsOrbitFlags[] = { - { "OrbitAsteroids", NULL, "Asteroids", NULL, NULL, G_CALLBACK(actionOrbitAsteroids), FALSE }, - { "OrbitComets", NULL, "Comets", NULL, NULL, G_CALLBACK(actionOrbitComets), FALSE }, - { "OrbitMoons", NULL, "Moons", NULL, NULL, G_CALLBACK(actionOrbitMoons), FALSE }, - { "OrbitPlanets", NULL, "Planets", NULL, NULL, G_CALLBACK(actionOrbitPlanets), FALSE }, - { "OrbitSpacecraft", NULL, "Spacecraft", NULL, NULL, G_CALLBACK(actionOrbitSpacecraft), FALSE }, +const inline std::array actionsOrbitFlags +{ + GtkToggleActionEntry{ "OrbitAsteroids", nullptr, "Asteroids", nullptr, nullptr, G_CALLBACK(actionOrbitAsteroids), FALSE }, + GtkToggleActionEntry{ "OrbitComets", nullptr, "Comets", nullptr, nullptr, G_CALLBACK(actionOrbitComets), FALSE }, + GtkToggleActionEntry{ "OrbitMoons", nullptr, "Moons", nullptr, nullptr, G_CALLBACK(actionOrbitMoons), FALSE }, + GtkToggleActionEntry{ "OrbitPlanets", nullptr, "Planets", nullptr, nullptr, G_CALLBACK(actionOrbitPlanets), FALSE }, + GtkToggleActionEntry{ "OrbitSpacecraft", nullptr, "Spacecraft", nullptr, nullptr, G_CALLBACK(actionOrbitSpacecraft), FALSE }, }; /* Label-Flag Actions */ -static const GtkToggleActionEntry actionsLabelFlags[] = { - { "LabelAsteroids", NULL, "Asteroids", "W", NULL, G_CALLBACK(actionLabelAsteroids), FALSE }, - { "LabelComets", NULL, "Comets", "W", NULL, G_CALLBACK(actionLabelComets), FALSE }, - { "LabelConstellations", NULL, "Constellations", "equal", NULL, G_CALLBACK(actionLabelConstellations), FALSE }, - { "LabelGalaxies", NULL, "Galaxies", "E", NULL, G_CALLBACK(actionLabelGalaxies), FALSE }, - { "LabelGlobulars", NULL, "Globulars", "E", NULL, G_CALLBACK(actionLabelGlobulars), FALSE }, - { "LabelLocations", NULL, "Locations", NULL, NULL, G_CALLBACK(actionLabelLocations), FALSE }, - { "LabelMoons", NULL, "Moons", "M", NULL, G_CALLBACK(actionLabelMoons), FALSE }, - { "LabelMinorMoons", NULL, "Minor Moons", "M", NULL, G_CALLBACK(actionLabelMinorMoons), FALSE }, - { "LabelNebulae", NULL, "Nebulae", NULL, NULL, G_CALLBACK(actionLabelNebulae), FALSE }, - { "LabelOpenClusters", NULL, "Open Clusters", NULL, NULL, G_CALLBACK(actionLabelOpenClusters), FALSE }, - { "LabelPlanets", NULL, "Planets", "P", NULL, G_CALLBACK(actionLabelPlanets), FALSE }, - { "LabelDwarfPlanets", NULL, "Dwarf Planets", "P", NULL, G_CALLBACK(actionLabelDwarfPlanets), FALSE }, - { "LabelSpacecraft", NULL, "Spacecraft", "N", NULL, G_CALLBACK(actionLabelSpacecraft), FALSE }, - { "LabelStars", NULL, "Stars", "B", NULL, G_CALLBACK(actionLabelStars), FALSE }, +const inline std::array actionsLabelFlags +{ + GtkToggleActionEntry{ "LabelAsteroids", nullptr, "Asteroids", "W", nullptr, G_CALLBACK(actionLabelAsteroids), FALSE }, + GtkToggleActionEntry{ "LabelComets", nullptr, "Comets", "W", nullptr, G_CALLBACK(actionLabelComets), FALSE }, + GtkToggleActionEntry{ "LabelConstellations", nullptr, "Constellations", "equal", nullptr, G_CALLBACK(actionLabelConstellations), FALSE }, + GtkToggleActionEntry{ "LabelGalaxies", nullptr, "Galaxies", "E", nullptr, G_CALLBACK(actionLabelGalaxies), FALSE }, + GtkToggleActionEntry{ "LabelGlobulars", nullptr, "Globulars", "E", nullptr, G_CALLBACK(actionLabelGlobulars), FALSE }, + GtkToggleActionEntry{ "LabelLocations", nullptr, "Locations", nullptr, nullptr, G_CALLBACK(actionLabelLocations), FALSE }, + GtkToggleActionEntry{ "LabelMoons", nullptr, "Moons", "M", nullptr, G_CALLBACK(actionLabelMoons), FALSE }, + GtkToggleActionEntry{ "LabelMinorMoons", nullptr, "Minor Moons", "M", nullptr, G_CALLBACK(actionLabelMinorMoons), FALSE }, + GtkToggleActionEntry{ "LabelNebulae", nullptr, "Nebulae", nullptr, nullptr, G_CALLBACK(actionLabelNebulae), FALSE }, + GtkToggleActionEntry{ "LabelOpenClusters", nullptr, "Open Clusters", nullptr, nullptr, G_CALLBACK(actionLabelOpenClusters), FALSE }, + GtkToggleActionEntry{ "LabelPlanets", nullptr, "Planets", "P", nullptr, G_CALLBACK(actionLabelPlanets), FALSE }, + GtkToggleActionEntry{ "LabelDwarfPlanets", nullptr, "Dwarf Planets", "P", nullptr, G_CALLBACK(actionLabelDwarfPlanets), FALSE }, + GtkToggleActionEntry{ "LabelSpacecraft", nullptr, "Spacecraft", "N", nullptr, G_CALLBACK(actionLabelSpacecraft), FALSE }, + GtkToggleActionEntry{ "LabelStars", nullptr, "Stars", "B", nullptr, G_CALLBACK(actionLabelStars), FALSE }, /* Does not appear to do anything yet: - { "LabelsLatin", NULL, "Labels in Latin", NULL, NULL, NULL, FALSE }, + GtkToggleActionEntry{ "LabelsLatin", nullptr, "Labels in Latin", nullptr, nullptr, nullptr, FALSE }, */ }; + +} // end namespace celestia::gtk diff --git a/src/celestia/hud.cpp b/src/celestia/hud.cpp index b760b57d47..33c5f6d57e 100644 --- a/src/celestia/hud.cpp +++ b/src/celestia/hud.cpp @@ -21,6 +21,9 @@ #include #include +#if FMT_VERSION < 90000 +#include +#endif #include #include @@ -249,7 +252,7 @@ displaySpeed(const util::NumberFormatter& formatter, Overlay& overlay, float spe // degree, only minutes and seconds are shown; if the angle is less than one minute, only // seconds are displayed. std::string -angleToStr(double angle) +angleToStr(double angle, const std::locale& loc) { int degrees; int minutes; @@ -258,20 +261,20 @@ angleToStr(double angle) if (degrees > 0) { - return fmt::format("{}" UTF8_DEGREE_SIGN "{:02d}' {:.1f}\"", + return fmt::format(loc, "{}" UTF8_DEGREE_SIGN "{:02d}' {:.1f}\"", degrees, abs(minutes), abs(seconds)); } if (minutes > 0) { - return fmt::format("{:02d}' {:.1f}\"", abs(minutes), abs(seconds)); + return fmt::format(loc, "{:02d}' {:.1f}\"", abs(minutes), abs(seconds)); } - return fmt::format("{:.2f}\"", abs(seconds)); + return fmt::format(loc, "{:.2f}\"", abs(seconds)); } void -displayApparentDiameter(Overlay& overlay, double radius, double distance) +displayApparentDiameter(Overlay& overlay, double radius, double distance, const std::locale& loc) { if (distance < radius) return; @@ -281,52 +284,53 @@ displayApparentDiameter(Overlay& overlay, double radius, double distance) // Only display the arc size if it's less than 160 degrees and greater // than one second--otherwise, it's probably not interesting data. if (arcSize < 160.0 && arcSize > 1.0 / 3600.0) - overlay.printf(_("Apparent diameter: %s\n"), angleToStr(arcSize)); + overlay.printf(_("Apparent diameter: %s\n"), angleToStr(arcSize, loc)); } void -displayDeclination(Overlay& overlay, double angle) +displayDeclination(Overlay& overlay, double angle, const std::locale& loc) { int degrees; int minutes; double seconds; astro::decimalToDegMinSec(angle, degrees, minutes, seconds); - overlay.printf(_("Dec: %+d%s %02d' %.1f\"\n"), - std::abs(degrees), UTF8_DEGREE_SIGN, - std::abs(minutes), std::abs(seconds)); + overlay.print(loc, _("Dec: {:+d}{} {:02d}' {:.1f}\"\n"), + std::abs(degrees), UTF8_DEGREE_SIGN, + std::abs(minutes), std::abs(seconds)); } void -displayRightAscension(Overlay& overlay, double angle) +displayRightAscension(Overlay& overlay, double angle, const std::locale& loc) { int hours; int minutes; double seconds; astro::decimalToHourMinSec(angle, hours, minutes, seconds); - overlay.printf(_("RA: %dh %02dm %.1fs\n"), - hours, abs(minutes), abs(seconds)); + overlay.print(loc, _("RA: {}h {:02}m {:.1f}s\n"), + hours, abs(minutes), abs(seconds)); } void displayApparentMagnitude(Overlay& overlay, float absMag, - double distance) + double distance, + const std::locale& loc) { if (distance > 32.6167) { - float appMag = astro::absToAppMag(absMag, (float) distance); - overlay.printf(_("Apparent magnitude: %.1f\n"), appMag); + float appMag = astro::absToAppMag(absMag, static_cast(distance)); + overlay.print(loc, _("Apparent magnitude: {:.1f}\n"), appMag); } else { - overlay.printf(_("Absolute magnitude: %.1f\n"), absMag); + overlay.print(loc, _("Absolute magnitude: {:.1f}\n"), absMag); } } void -displayRADec(Overlay& overlay, const Eigen::Vector3d& v) +displayRADec(Overlay& overlay, const Eigen::Vector3d& v, const std::locale& loc) { double phi = std::atan2(v.x(), v.z()) - celestia::numbers::pi / 2; if (phi < 0.0) @@ -339,8 +343,8 @@ displayRADec(Overlay& overlay, const Eigen::Vector3d& v) theta = -celestia::numbers::pi * 0.5 - theta; - displayRightAscension(overlay, math::radToDeg(phi)); - displayDeclination(overlay, math::radToDeg(theta)); + displayRightAscension(overlay, math::radToDeg(phi), loc); + displayDeclination(overlay, math::radToDeg(theta), loc); } // Display nicely formatted planetocentric/planetographic coordinates. @@ -353,7 +357,8 @@ displayPlanetocentricCoords(const util::NumberFormatter& formatter, double longitude, double latitude, double altitude, - MeasurementSystem measurement) + MeasurementSystem measurement, + const std::locale& loc) { char ewHemi = ' '; char nsHemi = ' '; @@ -399,9 +404,9 @@ displayPlanetocentricCoords(const util::NumberFormatter& formatter, lat = std::abs(math::radToDeg(latitude)); } - overlay.printf(_("%.6f%c %.6f%c %s"), - lat, nsHemi, lon, ewHemi, - DistanceKmToStr(formatter, altitude, 5, measurement)); + overlay.print(loc, _("{:.6f}{} {:.6f}{} {}"), + lat, nsHemi, lon, ewHemi, + DistanceKmToStr(formatter, altitude, 5, measurement)); } void @@ -411,7 +416,8 @@ displayStarInfo(const util::NumberFormatter& formatter, const Star& star, const Universe& universe, double distance, - const HudSettings& hudSettings) + const HudSettings& hudSettings, + const std::locale& loc) { overlay.printf(_("Distance: %s\n"), DistanceLyToStr(formatter, distance, 5, hudSettings.measurementSystem)); @@ -422,12 +428,12 @@ displayStarInfo(const util::NumberFormatter& formatter, } else { - overlay.printf(_("Abs (app) mag: %.2f (%.2f)\n"), - star.getAbsoluteMagnitude(), - star.getApparentMagnitude(float(distance))); + overlay.print(loc, _("Abs (app) mag: {:.2f} ({:.2f})\n"), + star.getAbsoluteMagnitude(), + star.getApparentMagnitude(float(distance))); if (star.getLuminosity() > 1.0e-10f) - overlay.print(_("Luminosity: {}x Sun\n"), formatter.format(star.getLuminosity(), 3, SigDigitNum)); + overlay.print(loc, _("Luminosity: {}x Sun\n"), formatter.format(star.getLuminosity(), 3, SigDigitNum)); const char* star_class; switch (star.getSpectralType()[0]) @@ -444,7 +450,7 @@ displayStarInfo(const util::NumberFormatter& formatter, overlay.printf(_("Class: %s\n"), star_class); displayApparentDiameter(overlay, star.getRadius(), - astro::lightYearsToKilometers(distance)); + astro::lightYearsToKilometers(distance), loc); if (detail > 1) { @@ -483,7 +489,8 @@ void displayDSOinfo(const util::NumberFormatter& formatter, Overlay& overlay, const DeepSkyObject& dso, double distance, - MeasurementSystem measurement) + MeasurementSystem measurement, + const std::locale& loc) { overlay.print(dso.getDescription()); overlay.print("\n"); @@ -501,12 +508,13 @@ void displayDSOinfo(const util::NumberFormatter& formatter, overlay.printf(_("Radius: %s\n"), DistanceLyToStr(formatter, dso.getRadius(), 5, measurement)); - displayApparentDiameter(overlay, dso.getRadius(), distance); + displayApparentDiameter(overlay, dso.getRadius(), distance, loc); if (dso.getAbsoluteMagnitude() > DSO_DEFAULT_ABS_MAGNITUDE) { displayApparentMagnitude(overlay, dso.getAbsoluteMagnitude(), - distance); + distance, + loc); } } @@ -517,7 +525,8 @@ displayPlanetInfo(const util::NumberFormatter& formatter, Body& body, double t, const Eigen::Vector3d& viewVec, - const HudSettings& hudSettings) + const HudSettings& hudSettings, + const std::locale& loc) { double distanceKm = viewVec.norm(); double distance = distanceKm - body.getRadius(); @@ -532,7 +541,7 @@ displayPlanetInfo(const util::NumberFormatter& formatter, overlay.printf(_("Radius: %s\n"), DistanceKmToStr(formatter, body.getRadius(), 5, hudSettings.measurementSystem)); - displayApparentDiameter(overlay, body.getRadius(), distanceKm); + displayApparentDiameter(overlay, body.getRadius(), distanceKm, loc); // Display the phase angle @@ -568,7 +577,7 @@ displayPlanetInfo(const util::NumberFormatter& formatter, sunVec.normalize(); double cosPhaseAngle = std::clamp(sunVec.dot(viewVec.normalized()), -1.0, 1.0); double phaseAngle = acos(cosPhaseAngle); - overlay.printf(_("Phase angle: %.1f%s\n"), math::radToDeg(phaseAngle), UTF8_DEGREE_SIGN); + overlay.print(loc, _("Phase angle: {:.1f}{}\n"), math::radToDeg(phaseAngle), UTF8_DEGREE_SIGN); } } @@ -604,7 +613,8 @@ displayLocationInfo(const util::NumberFormatter& formatter, Overlay& overlay, const Location& location, double distanceKm, - MeasurementSystem measurement) + MeasurementSystem measurement, + const std::locale& loc) { overlay.printf(_("Distance: %s\n"), DistanceKmToStr(formatter, distanceKm, 5, measurement)); @@ -615,7 +625,7 @@ displayLocationInfo(const util::NumberFormatter& formatter, Eigen::Vector3f locPos = location.getPosition(); Eigen::Vector3d lonLatAlt = body->cartesianToPlanetocentric(locPos.cast()); displayPlanetocentricCoords(formatter, overlay, *body, - lonLatAlt.x(), lonLatAlt.y(), lonLatAlt.z(), measurement); + lonLatAlt.x(), lonLatAlt.y(), lonLatAlt.z(), measurement, loc); } std::string @@ -692,6 +702,16 @@ HudFonts::setTitleFont(const std::shared_ptr& f) m_titleEmWidth = engine::TextLayout::getTextWidth("M", f.get()); } +Hud::Hud(const std::locale& loc) : + loc(loc), +#ifdef USE_ICU + m_numberFormatter(std::make_unique()) +#else + m_numberFormatter(std::make_unique(loc)) +#endif +{ +} + Hud::~Hud() = default; int @@ -849,8 +869,6 @@ Hud::renderOverlay(const WindowMetrics& metrics, views.renderBorders(m_overlay.get(), metrics, timeInfo.currentTime); - setlocale(LC_NUMERIC, ""); - if (m_hudDetail > 0 && util::is_set(m_hudSettings.overlayElements, HudElements::ShowTime)) renderTimeInfo(metrics, sim, timeInfo); @@ -865,7 +883,7 @@ Hud::renderOverlay(const WindowMetrics& metrics, m_overlay->beginText(); m_overlay->print("\n"); if (m_hudSettings.showFPSCounter) - m_overlay->printf(_("FPS: %.1f\n"), timeInfo.fps); + m_overlay->print(loc, _("FPS: {:.1f}\n"), timeInfo.fps); else m_overlay->print("\n"); @@ -907,7 +925,6 @@ Hud::renderOverlay(const WindowMetrics& metrics, } m_overlay->end(); - setlocale(LC_NUMERIC, "C"); } void @@ -959,11 +976,11 @@ Hud::renderTimeInfo(const WindowMetrics& metrics, const Simulation* sim, const T } else if (std::abs(sim->getTimeScale()) > 1.0) { - m_overlay->printf(_("%.6g x faster"), sim->getTimeScale()); // XXX: %'.12g + m_overlay->print(loc, _("{:.6g} x faster"), sim->getTimeScale()); // XXX: %'.12g } else { - m_overlay->printf(_("%.6g x slower"), 1.0 / sim->getTimeScale()); // XXX: %'.12g + m_overlay->print(loc, _("{:.6g} x slower"), 1.0 / sim->getTimeScale()); // XXX: %'.12g } if (sim->getPauseState() == true) @@ -1039,7 +1056,7 @@ Hud::renderFrameInfo(const WindowMetrics& metrics, const Simulation* sim) // Field of view const Observer* activeObserver = sim->getActiveObserver(); float fov = math::radToDeg(activeObserver->getFOV()); - m_overlay->printf(_("FOV: %s (%.2fx)\n"), angleToStr(fov), activeObserver->getZoom()); + m_overlay->print(loc, _("FOV: {} ({:.2f}x)\n"), angleToStr(fov, loc), activeObserver->getZoom()); m_overlay->endText(); m_overlay->restorePos(); } @@ -1076,7 +1093,8 @@ Hud::renderSelectionInfo(const WindowMetrics& metrics, *(sel.star()), *(sim->getUniverse()), astro::kilometersToLightYears(v.norm()), - m_hudSettings); + m_hudSettings, + loc); } break; @@ -1096,7 +1114,8 @@ Hud::renderSelectionInfo(const WindowMetrics& metrics, *m_overlay, *sel.deepsky(), astro::kilometersToLightYears(v.norm()) - sel.deepsky()->getRadius(), - m_hudSettings.measurementSystem); + m_hudSettings.measurementSystem, + loc); } break; @@ -1119,7 +1138,8 @@ Hud::renderSelectionInfo(const WindowMetrics& metrics, *(sel.body()), sim->getTime(), v, - m_hudSettings); + m_hudSettings, + loc); } break; @@ -1132,7 +1152,8 @@ Hud::renderSelectionInfo(const WindowMetrics& metrics, *m_overlay, *(sel.location()), v.norm(), - m_hudSettings.measurementSystem); + m_hudSettings.measurementSystem, + loc); break; default: @@ -1158,7 +1179,7 @@ Hud::renderSelectionInfo(const WindowMetrics& metrics, // near the Earth. Eigen::Vector3d vEarth = sel.getPosition(sim->getTime()).offsetFromKm(Selection(earth).getPosition(sim->getTime())); vEarth = math::XRotation(astro::J2000Obliquity) * vEarth; - displayRADec(*m_overlay, vEarth); + displayRADec(*m_overlay, vEarth, loc); } } @@ -1210,10 +1231,10 @@ Hud::renderMovieCapture(const WindowMetrics& metrics, const MovieCapture& movieC m_overlay->moveBy(static_cast((metrics.width - movieWidth) / 2), static_cast((metrics.height + movieHeight) / 2 + 2)); m_overlay->beginText(); - m_overlay->printf(_("%dx%d at %.2f fps %s"), - movieWidth, movieHeight, - movieCapture.getFrameRate(), - movieCapture.recordingStatus() ? _("Recording") : _("Paused")); + m_overlay->print(loc, _("{}x{} at {:.2f} fps {}"), + movieWidth, movieHeight, + movieCapture.getFrameRate(), + movieCapture.recordingStatus() ? _("Recording") : _("Paused")); m_overlay->endText(); m_overlay->restorePos(); @@ -1225,7 +1246,7 @@ Hud::renderMovieCapture(const WindowMetrics& metrics, const MovieCapture& movieC auto min = static_cast(sec / 60.0f); sec -= static_cast(min) * 60.0f; m_overlay->beginText(); - m_overlay->print("{:3d}:{:05.2f}", min, sec); + m_overlay->print(loc, "{:3d}:{:05.2f}", min, sec); m_overlay->endText(); m_overlay->restorePos(); diff --git a/src/celestia/hud.h b/src/celestia/hud.h index 7387a6d930..6a24094fbd 100644 --- a/src/celestia/hud.h +++ b/src/celestia/hud.h @@ -13,9 +13,7 @@ #pragma once #include -#ifndef USE_ICU #include -#endif #include #include #include @@ -125,7 +123,7 @@ class Hud PassToScript = 0x02, }; - Hud() = default; + explicit Hud(const std::locale&); ~Hud(); int detail() const; @@ -175,12 +173,10 @@ class Hud std::unique_ptr m_image; + std::locale loc; + std::unique_ptr m_dateFormatter{ std::make_unique() }; -#ifdef USE_ICU - std::unique_ptr m_numberFormatter{ std::make_unique() }; -#else - std::unique_ptr m_numberFormatter{ std::make_unique(std::locale("")) }; -#endif + std::unique_ptr m_numberFormatter; celestia::astro::Date::Format m_dateFormat{ celestia::astro::Date::Locale }; int m_dateStrWidth{ 0 }; diff --git a/src/celestia/qt/qtappwin.cpp b/src/celestia/qt/qtappwin.cpp index 2960c0ad53..ed56cc104c 100644 --- a/src/celestia/qt/qtappwin.cpp +++ b/src/celestia/qt/qtappwin.cpp @@ -343,14 +343,12 @@ CelestiaAppWindow::init(const CelestiaCommandLineOptions& options) toolsDock = new QDockWidget(_("Celestial Browser"), this); toolsDock->setObjectName("celestia-tools-dock"); - toolsDock->setAllowedAreas(Qt::LeftDockWidgetArea | - Qt::RightDockWidgetArea); + toolsDock->setAllowedAreas(static_cast(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea)); // Info browser for a selected object infoPanel = new InfoPanel(m_appCore, _("Info Browser"), this); infoPanel->setObjectName("info-panel"); - infoPanel->setAllowedAreas(Qt::LeftDockWidgetArea | - Qt::RightDockWidgetArea); + infoPanel->setAllowedAreas(static_cast(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea)); infoPanel->setVisible(false); // Create the various browser widgets @@ -387,8 +385,7 @@ CelestiaAppWindow::init(const CelestiaCommandLineOptions& options) eventFinder = new EventFinder(m_appCore, _("Event Finder"), this); eventFinder->setObjectName("event-finder"); - eventFinder->setAllowedAreas(Qt::LeftDockWidgetArea | - Qt::RightDockWidgetArea); + eventFinder->setAllowedAreas(static_cast(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea)); addDockWidget(Qt::LeftDockWidgetArea, eventFinder); eventFinder->setVisible(false); //addDockWidget(Qt::DockWidgetArea, eventFinder); diff --git a/src/celestia/qt/qtcelestialbrowser.cpp b/src/celestia/qt/qtcelestialbrowser.cpp index 70335f82e1..5217e73f1d 100644 --- a/src/celestia/qt/qtcelestialbrowser.cpp +++ b/src/celestia/qt/qtcelestialbrowser.cpp @@ -147,7 +147,7 @@ CelestialBrowser::StarTableModel::objectAtIndex(const QModelIndex& _index) const Qt::ItemFlags CelestialBrowser::StarTableModel::flags(const QModelIndex& /*unused*/) const { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return static_cast(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } // Override QAbstractTableModel::data() diff --git a/src/celestia/qt/qtdeepskybrowser.cpp b/src/celestia/qt/qtdeepskybrowser.cpp index 1f15a9b8d0..28efa33d2b 100644 --- a/src/celestia/qt/qtdeepskybrowser.cpp +++ b/src/celestia/qt/qtdeepskybrowser.cpp @@ -281,7 +281,7 @@ DeepSkyBrowser::DSOTableModel::objectAtIndex(const QModelIndex& _index) const Qt::ItemFlags DeepSkyBrowser::DSOTableModel::flags(const QModelIndex& /*unused*/) const { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return static_cast(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } // Override QAbstractTableModel::data() diff --git a/src/celestia/qt/qteventfinder.cpp b/src/celestia/qt/qteventfinder.cpp index 351f3e6ec7..9eba3f1e58 100644 --- a/src/celestia/qt/qteventfinder.cpp +++ b/src/celestia/qt/qteventfinder.cpp @@ -162,7 +162,7 @@ class EventFinder::EventTableModel : public QAbstractTableModel Qt::ItemFlags EventFinder::EventTableModel::flags(const QModelIndex& /*unused*/) const { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return static_cast(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } QVariant diff --git a/src/celestia/qt/qtsolarsystembrowser.cpp b/src/celestia/qt/qtsolarsystembrowser.cpp index 1f98dcf373..a7cebc1e91 100644 --- a/src/celestia/qt/qtsolarsystembrowser.cpp +++ b/src/celestia/qt/qtsolarsystembrowser.cpp @@ -622,7 +622,7 @@ SolarSystemBrowser::SolarSystemTreeModel::flags(const QModelIndex& index) const if (!index.isValid()) return {}; - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return static_cast(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } // Override QAbstractTableModel::data() diff --git a/src/celestia/qt5/data/CMakeLists.txt b/src/celestia/qt5/data/CMakeLists.txt index c5b6fc4bfc..750feede5f 100644 --- a/src/celestia/qt5/data/CMakeLists.txt +++ b/src/celestia/qt5/data/CMakeLists.txt @@ -1,10 +1,15 @@ +set(METAINFO_ID "space.celestiaproject.Celestia-qt5") +set(METAINFO_NAME "Celestia (Qt5)") +set(METAINFO_DESKTOP "celestia-qt5.desktop") +configure_file("../../data/space.celestiaproject.Celestia.metainfo.xml.in" "${METAINFO_ID}.metainfo.xml") + install( - FILES celestia-qt5.desktop + FILES "${METAINFO_DESKTOP}" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications" COMPONENT qt5gui ) install( - FILES space.celestia.celestia_qt5.metainfo.xml + FILES "${METAINFO_ID}.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo" COMPONENT qt5gui ) diff --git a/src/celestia/qt5/data/space.celestia.celestia_qt5.metainfo.xml b/src/celestia/qt5/data/space.celestia.celestia_qt5.metainfo.xml deleted file mode 100644 index 5c248d7451..0000000000 --- a/src/celestia/qt5/data/space.celestia.celestia_qt5.metainfo.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - space.celestia.celestia_qt5 - MIT - GPL-2.0+ - Celestia (Qt5) - Explore the universe - -

- Celestia provides photo-realistic, real-time, three-dimensional viewing of - the Solar System, the Galaxy and the Universe. -

-

- It is an easy to use, freely-distributed, multi-platform, open source, - software package which has become a valuable tool for astronomy education. - Used in homes, schools, museums and planetariums around the world, it also - is used as a visualization tool by space mission designers. -

-
- celestia-qt5.desktop - https://celestiaproject.space - - https://celestiaproject.space/images/gallery/cassini.jpg - https://celestiaproject.space/images/gallery/earth.jpg - https://celestiaproject.space/images/gallery/europa.jpg - https://celestiaproject.space/images/gallery/proxima.png - -
diff --git a/src/celestia/qt6/data/CMakeLists.txt b/src/celestia/qt6/data/CMakeLists.txt index 0cb00d1316..2fb671e204 100644 --- a/src/celestia/qt6/data/CMakeLists.txt +++ b/src/celestia/qt6/data/CMakeLists.txt @@ -1,10 +1,15 @@ +set(METAINFO_ID "space.celestiaproject.Celestia-qt6") +set(METAINFO_NAME "Celestia (Qt6)") +set(METAINFO_DESKTOP "celestia-qt6.desktop") +configure_file("../../data/space.celestiaproject.Celestia.metainfo.xml.in" "${METAINFO_ID}.metainfo.xml") + install( - FILES celestia-qt6.desktop + FILES "${METAINFO_DESKTOP}" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications" COMPONENT qt6gui ) install( - FILES space.celestia.celestia_qt6.metainfo.xml + FILES "${METAINFO_ID}.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo" COMPONENT qt6gui ) diff --git a/src/celestia/qt6/data/space.celestia.celestia_qt6.metainfo.xml b/src/celestia/qt6/data/space.celestia.celestia_qt6.metainfo.xml deleted file mode 100644 index 85bb10dbf6..0000000000 --- a/src/celestia/qt6/data/space.celestia.celestia_qt6.metainfo.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - space.celestia.celestia_qt6 - MIT - GPL-2.0+ - Celestia (Qt6) - Explore the universe - -

- Celestia provides photo-realistic, real-time, three-dimensional viewing of - the Solar System, the Galaxy and the Universe. -

-

- It is an easy to use, freely-distributed, multi-platform, open source, - software package which has become a valuable tool for astronomy education. - Used in homes, schools, museums and planetariums around the world, it also - is used as a visualization tool by space mission designers. -

-
- celestia-qt6.desktop - https://celestiaproject.space - - https://celestiaproject.space/images/gallery/cassini.jpg - https://celestiaproject.space/images/gallery/earth.jpg - https://celestiaproject.space/images/gallery/europa.jpg - https://celestiaproject.space/images/gallery/proxima.png - -
diff --git a/src/celestia/sdl/data/CMakeLists.txt b/src/celestia/sdl/data/CMakeLists.txt index 96b72cc2b6..805ff3b236 100644 --- a/src/celestia/sdl/data/CMakeLists.txt +++ b/src/celestia/sdl/data/CMakeLists.txt @@ -1,10 +1,15 @@ +set(METAINFO_ID "space.celestiaproject.Celestia-sdl") +set(METAINFO_NAME "Celestia (SDL)") +set(METAINFO_DESKTOP "celestia-sdl.desktop") +configure_file("../../data/space.celestiaproject.Celestia.metainfo.xml.in" "${METAINFO_ID}.metainfo.xml") + install( - FILES celestia-sdl.desktop + FILES "${METAINFO_DESKTOP}" DESTINATION "${CMAKE_INSTALL_DATADIR}/applications" COMPONENT sdlgui ) install( - FILES space.celestia.celestia_sdl.metainfo.xml + FILES "${METAINFO_ID}.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo" COMPONENT sdlgui ) diff --git a/src/celestia/sdl/data/space.celestia.celestia_sdl.metainfo.xml b/src/celestia/sdl/data/space.celestia.celestia_sdl.metainfo.xml deleted file mode 100644 index fd16861bcd..0000000000 --- a/src/celestia/sdl/data/space.celestia.celestia_sdl.metainfo.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - space.celestia.celestia_sdl - MIT - GPL-2.0+ - Celestia (SDL) - Explore the universe - -

- Celestia provides photo-realistic, real-time, three-dimensional viewing of - the Solar System, the Galaxy and the Universe. -

-

- It is an easy to use, freely-distributed, multi-platform, open source, - software package which has become a valuable tool for astronomy education. - Used in homes, schools, museums and planetariums around the world, it also - is used as a visualization tool by space mission designers. -

-
- celestia-sdl.desktop - https://celestiaproject.space - - https://celestiaproject.space/images/gallery/cassini.jpg - https://celestiaproject.space/images/gallery/earth.jpg - https://celestiaproject.space/images/gallery/europa.jpg - https://celestiaproject.space/images/gallery/proxima.png - -
diff --git a/src/celestia/sdl/sdlmain.cpp b/src/celestia/sdl/sdlmain.cpp index f49d926bb4..d140a784b0 100644 --- a/src/celestia/sdl/sdlmain.cpp +++ b/src/celestia/sdl/sdlmain.cpp @@ -31,8 +31,12 @@ #include #endif -namespace celestia +namespace celestia::sdl { + +namespace +{ + class SDL_Alerter : public CelestiaCore::Alerter { SDL_Window* window { nullptr }; @@ -307,7 +311,7 @@ SDL_Application::update() return RunLoopState::Normal; } -static int +int toCelestiaKey(SDL_Keycode key) { switch (key) @@ -442,7 +446,7 @@ SDL_Application::handleTextInputEvent(const SDL_TextInputEvent &event) m_appCore->charEntered(event.text, 0); } -static int +int toCelestiaButton(int button) { switch (button) @@ -611,7 +615,7 @@ SDL_Application::pasteURL() SDL_free(str); } -static void +void FatalErrorImpl(fmt::string_view format, fmt::format_args args) { auto message = fmt::vformat(format, args); @@ -623,13 +627,14 @@ FatalErrorImpl(fmt::string_view format, fmt::format_args args) fmt::print(stderr, "{}\n", message); } -template void +template +void FatalError(const char *format, const Args&... args) { FatalErrorImpl(fmt::string_view(format), fmt::make_format_args(args...)); } -static void +void DumpGLInfo() { const char* s; @@ -709,10 +714,13 @@ sdlmain(int /* argc */, char ** /* argv */) return 0; } -} // namespace + +} // end unnamed namespace + +} // end namespace celestia::sdl int main(int argc, char **argv) { - return celestia::sdlmain(argc, argv); + return celestia::sdl::sdlmain(argc, argv); } diff --git a/src/celutil/CMakeLists.txt b/src/celutil/CMakeLists.txt index 284c2b34df..5139605819 100644 --- a/src/celutil/CMakeLists.txt +++ b/src/celutil/CMakeLists.txt @@ -18,6 +18,7 @@ set(CELUTIL_SOURCES greek.h includeicu.h intrusiveptr.h + localeutil.h logger.cpp logger.h ranges.h diff --git a/src/celutil/localeutil.h b/src/celutil/localeutil.h new file mode 100644 index 0000000000..7c70aa3ad4 --- /dev/null +++ b/src/celutil/localeutil.h @@ -0,0 +1,46 @@ +// localeutil.h +// +// Copyright (C) 2024-present, the Celestia Development Team +// +// This program 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. + +#pragma once + +#include // for strtod_l +#if defined __APPLE__ || defined(__FreeBSD__) +# include // for LC_NUMERIC_MASK on OS X +#endif + +#ifdef _MSC_VER +typedef _locale_t locale_t; + +enum { LC_NUMERIC_MASK = LC_NUMERIC }; + +static inline locale_t newlocale(int category_mask, const char *locale, locale_t) +{ + return _create_locale(category_mask, locale); +} + +static inline void freelocale(locale_t locale) +{ + _free_locale(locale); +} + +static inline float strtof_l(const char *nptr, char **endptr, locale_t loc) +{ + return _strtof_l(nptr, endptr, loc); +} + +static inline double strtod_l(const char *nptr, char **endptr, locale_t loc) +{ + return _strtod_l(nptr, endptr, loc); +} + +static inline long double strtold_l(const char *nptr, char **endptr, locale_t loc) +{ + return _strtold_l(nptr, endptr, loc); +} +#endif diff --git a/src/tools/cmod/cmodview/modelviewwidget.cpp b/src/tools/cmod/cmodview/modelviewwidget.cpp index f1189e86c1..7588991611 100644 --- a/src/tools/cmod/cmodview/modelviewwidget.cpp +++ b/src/tools/cmod/cmodview/modelviewwidget.cpp @@ -904,9 +904,6 @@ ModelViewWidget::setAmbientLight(bool enable) void ModelViewWidget::setShadows(bool enable) { - if (!FramebufferObject::isSupported()) - return; - if (enable != m_shadowsEnabled) { m_shadowsEnabled = enable;