diff --git a/develnext/build.gradle b/develnext/build.gradle index 55abeac6..88814efe 100644 --- a/develnext/build.gradle +++ b/develnext/build.gradle @@ -1,152 +1,202 @@ -apply plugin: 'application' - -project.version = '1.0' - -repositories { - mavenLocal() - jcenter() - mavenCentral() -} - -sourceSets { - main.resources.srcDirs = ['src'] -} - -mainClassName = 'php.runtime.launcher.Launcher' -jar.archiveName = 'DevelNext.jar' - -manifest { - attributes 'Main-Class': 'php.runtime.launcher.Launcher' -} - -task distPatchZip(type: Zip, dependsOn: ['clean', 'distPatch']) { - from "$project.buildDir/install/$project.name" - archiveName "DevelNext.Patch.zip" - - doLast { - def uploadPath = System.getProperty("uploadPath", "E:/Upload") - - if (new File(uploadPath).isDirectory()) { - copy { - from distPatchZip.archivePath - into "$uploadPath/YandexDisk" - } - } - } -} - - -task distPatch(dependsOn: ['clean', 'installDist']) { - doLast { - if (System.properties['os.name'].toLowerCase().contains('windows')) { - exec { - commandLine "$project.rootDir/develnext-tools/Launch4j/launch4jc.exe" - args "$project.rootDir/develnext/launcher/winLauncher.xml" - } - } - - copy { - from "$project.rootDir/develnext/launcher/DevelNext.exe" - into "$project.buildDir/install/$project.name" - } - - copy { - from "$project.rootDir/develnext/misc" - into "$project.buildDir/install/$project.name" - } - } -} - - -task distIdeWindows(dependsOn: ['distIde']) { - doLast { - delete "$project.buildDir/install/$project.name/tools/jreLinux" - } -} - -task distIdeLinux(dependsOn: ['distIde']) { - doLast { - delete "$project.buildDir/install/$project.name/tools/jre" - file("$project.buildDir/install/$project.name/tools/jreLinux").renameTo(file("$project.buildDir/install/$project.name/tools/jre")) - } -} - -task distIde(dependsOn: ['installDist']) { - doLast { - if (System.properties['os.name'].toLowerCase().contains('windows')) { - exec { - commandLine "$project.rootDir/develnext-tools/Launch4j/launch4jc.exe" - args "$project.rootDir/develnext/launcher/winLauncher.xml" - } - } - - copy { - from "$project.rootDir/develnext-tools" - into "$project.buildDir/install/$project.name/tools" - } - - copy { - from "$project.rootDir/develnext/launcher/DevelNext.exe" - into "$project.buildDir/install/$project.name" - } - - copy { - from "$project.rootDir/develnext/misc" - into "$project.buildDir/install/$project.name" - } - } -} - -task distIdeWindowsSetup(dependsOn: ['distIdeWindows']) { - doLast { - def issFile = "$project.rootDir/develnext/windowsSetup/innosetup.iss".replace("\\", "/") - def innoSetupBin = "$project.rootDir/develnext-tools/innoSetup/ISCC.exe".replace("\\", "/") - - exec { - commandLine innoSetupBin, '/Qp', issFile - } - - def uploadPath = System.getProperty("uploadPath", "E:/Upload") - - if (new File(uploadPath).isDirectory()) { - copy { - from "$project.buildDir/distributions/DevelNextSetup.exe" - into "$uploadPath/YandexDisk" - } - } - } -} - -task distIdeLinuxSetup(type: Tar, dependsOn: ['distIdeLinux']) { - def installDir = "$project.buildDir/install/$project.name" - - compression = Compression.GZIP - archiveName "DevelNextLinux.tar.gz" - - from(installDir) { - exclude('*.sh') - exclude('bin/develnext') - exclude('tools/gradle/bin/gradle') - exclude('tools/jre/bin/java') - } - - from(installDir) { - include('*.sh') - include('bin/develnext') - include('tools/gradle/bin/gradle') - include('tools/jre/bin/java') - - fileMode = 0755 - } - - doLast { - def uploadPath = System.getProperty("uploadPath", "E:/Upload") - - if (new File(uploadPath).isDirectory()) { - copy { - from distIdeLinuxSetup.archivePath - into "$uploadPath/YandexDisk" - } - } - } -} +apply plugin: 'application' + +project.version = '1.0' + +repositories { + mavenLocal() + jcenter() + mavenCentral() +} + +sourceSets { + main.resources.srcDirs = ['src'] +} + +run { + mainClassName = 'php.runtime.launcher.Launcher' + jvmArgs += ["-Dfile.encoding=UTF-8", "-Xms256m", "-Xms1280m"] +} + +jar.archiveName = 'DevelNext.jar' + +manifest { + attributes 'Main-Class': 'php.runtime.launcher.Launcher' +} + +task distWindowsPatch(type: Zip, dependsOn: ['clean', 'distPatch']) { + from "$project.buildDir/install/$project.name" + archiveName "DevelNext.WindowsPatch.zip" + + doLast { + def issFile = "$project.rootDir/develnext/windowsSetup/innopatchsetup.iss".replace("\\", "/") + def innoSetupBin = "$project.rootDir/develnext-tools/innoSetup/ISCC.exe".replace("\\", "/") + + exec { + commandLine innoSetupBin, '/Qp', issFile + } + + def uploadPath = System.getProperty("uploadPath", "E:/Upload") + + if (new File(uploadPath).isDirectory()) { + copy { + from "$project.buildDir/distributions/DevelNext.WindowsPatch.exe" + into "$uploadPath/YandexDisk" + } + + copy { + from distWindowsPatch.archivePath + into "$uploadPath/YandexDisk" + } + } + } +} + +task distLinuxPatch(type: Tar, dependsOn: ['clean', 'distPatch']) { + def installDir = "$project.buildDir/install/$project.name" + + compression = Compression.GZIP + archiveName "DevelNext.LinuxPatch.tar.gz" + + from(installDir) { + exclude('*.sh') + exclude('bin/develnext') + exclude('tools/gradle/bin/gradle') + exclude('tools/jre/bin/java') + } + + from(installDir) { + include('*.sh') + include('bin/develnext') + include('tools/gradle/bin/gradle') + include('tools/jre/bin/java') + + fileMode = 0755 + } + + doLast { + def uploadPath = System.getProperty("uploadPath", "E:/Upload") + + if (new File(uploadPath).isDirectory()) { + copy { + from distLinuxPatch.archivePath + into "$uploadPath/YandexDisk" + } + } + } +} + + +task distPatch(dependsOn: ['clean', 'installDist']) { + doLast { + if (System.properties['os.name'].toLowerCase().contains('windows')) { + exec { + commandLine "$project.rootDir/develnext-tools/Launch4j/launch4jc.exe" + args "$project.rootDir/develnext/launcher/winLauncher.xml" + } + } + + copy { + from "$project.rootDir/develnext/launcher/DevelNext.exe" + into "$project.buildDir/install/$project.name" + } + + copy { + from "$project.rootDir/develnext/misc" + into "$project.buildDir/install/$project.name" + } + } +} + + +task distIdeWindows(dependsOn: ['distIde']) { + doLast { + delete "$project.buildDir/install/$project.name/tools/jreLinux" + } +} + +task distIdeLinux(dependsOn: ['distIde']) { + doLast { + delete "$project.buildDir/install/$project.name/tools/jre" + file("$project.buildDir/install/$project.name/tools/jreLinux").renameTo(file("$project.buildDir/install/$project.name/tools/jre")) + } +} + +task distIde(dependsOn: ['installDist']) { + doLast { + if (System.properties['os.name'].toLowerCase().contains('windows')) { + exec { + commandLine "$project.rootDir/develnext-tools/Launch4j/launch4jc.exe" + args "$project.rootDir/develnext/launcher/winLauncher.xml" + } + } + + copy { + from "$project.rootDir/develnext-tools" + into "$project.buildDir/install/$project.name/tools" + } + + copy { + from "$project.rootDir/develnext/launcher/DevelNext.exe" + into "$project.buildDir/install/$project.name" + } + + copy { + from "$project.rootDir/develnext/misc" + into "$project.buildDir/install/$project.name" + } + } +} + +task distIdeWindowsSetup(dependsOn: ['distIdeWindows']) { + doLast { + def issFile = "$project.rootDir/develnext/windowsSetup/innosetup.iss".replace("\\", "/") + def innoSetupBin = "$project.rootDir/develnext-tools/innoSetup/ISCC.exe".replace("\\", "/") + + exec { + commandLine innoSetupBin, '/Qp', issFile + } + + def uploadPath = System.getProperty("uploadPath", "E:/Upload") + + if (new File(uploadPath).isDirectory()) { + copy { + from "$project.buildDir/distributions/DevelNextSetup.exe" + into "$uploadPath/YandexDisk" + } + } + } +} + +task distIdeLinuxSetup(type: Tar, dependsOn: ['distIdeLinux']) { + def installDir = "$project.buildDir/install/$project.name" + + compression = Compression.GZIP + archiveName "DevelNextLinux.tar.gz" + + from(installDir) { + exclude('*.sh') + exclude('bin/develnext') + exclude('tools/gradle/bin/gradle') + exclude('tools/jre/bin/java') + } + + from(installDir) { + include('*.sh') + include('bin/develnext') + include('tools/gradle/bin/gradle') + include('tools/jre/bin/java') + + fileMode = 0755 + } + + doLast { + def uploadPath = System.getProperty("uploadPath", "E:/Upload") + + if (new File(uploadPath).isDirectory()) { + copy { + from distIdeLinuxSetup.archivePath + into "$uploadPath/YandexDisk" + } + } + } +} diff --git a/develnext/launcher/DevelNext.exe b/develnext/launcher/DevelNext.exe index deab156b..42d01813 100644 Binary files a/develnext/launcher/DevelNext.exe and b/develnext/launcher/DevelNext.exe differ diff --git a/develnext/launcher/winLauncher.xml b/develnext/launcher/winLauncher.xml index 3468c731..f44c3694 100644 --- a/develnext/launcher/winLauncher.xml +++ b/develnext/launcher/winLauncher.xml @@ -1,44 +1,46 @@ - - - true - gui - DevelNext.exe - - - . - normal - http://java.com/download - http://develnext.org - false - false - - DevelNext.ico - - php.runtime.launcher.Launcher - lib/* - - - tools/jre - false - false - - - jreOnly - 64/32 - 256 - 1536 - -Dfile.encoding=UTF-8 -Ddevelnext.launcher=root - - - 4.0.0.0 - - - DevelNext IDE - 2016, OpenSource - 4.0.0.0 - - - DevelNext - Dim-S Software - DevelNext - DevelNext.exe - + + + true + gui + DevelNext.exe + + + . + normal + http://java.com/download + http://develnext.org + false + false + + DevelNext.ico + + php.runtime.launcher.Launcher + lib/* + + + tools/jre + false + false + + + jreOnly + 64/32 + 256 + 1280 + + -Dfile.encoding=UTF-8 + -Ddevelnext.launcher=root + + + 4.0.0.0 + - + DevelNext IDE + 2016, OpenSource + 4.0.0.0 + - + DevelNext + Dim-S Software + DevelNext + DevelNext.exe + \ No newline at end of file diff --git a/develnext/misc/DevelNext.sh b/develnext/misc/DevelNext.sh index 759800a2..af20bb0b 100644 --- a/develnext/misc/DevelNext.sh +++ b/develnext/misc/DevelNext.sh @@ -1,3 +1,3 @@ #!/bin/sh -tools/jre/bin/java -Dfile.encoding=UTF-8 -Ddevelnext.launcher=root -cp "./lib/*" php.runtime.launcher.Launcher $* \ No newline at end of file +tools/jre/bin/java -Dfile.encoding=UTF-8 -Ddevelnext.launcher=root -Xms256m -Xmx1280m -cp "./lib/*" php.runtime.launcher.Launcher $* \ No newline at end of file diff --git a/develnext/misc/history.txt b/develnext/misc/history.txt index 33507bab..dc7c7ee2 100644 --- a/develnext/misc/history.txt +++ b/develnext/misc/history.txt @@ -1,375 +1,386 @@ -Alpha-4 (21.02.2016) ------------- -*Основные фичи* -+ Система помощи, онлайн справка, F.A.Q. -+ Возможность добавлять клонов в редакторе, а не только во время выполнения. -+ Табы открытых редакторов теперь можно перетаскивать, менять местами. -+ Возможность легко сменить тип события, сохраняя его код и действия. -+ Новые события глобальной клавиатуры, с логикой работы как в играх. -+ Новое событие "Каждый кадр", которое отрабатывает каждый кадр существования объекта. -+ Новое игровое поведение - "Ограниченное перемещение". -+ В редакторе форм новая возможность настраивать способ отображения сетки для выравнивания объектов. -+ Новый демо-проект "Арканоид" для демонстрации игровых возможностей. -+ Множество мелких улучшений и доработок, см. ниже + патчи A и B. -+ Добавлено действие для сворачивания и разворачивания формы во вкладке объекты. - -- Добавлена система онлайн помощи, поиск по документации и сама документация с ответами на многие вопросы. -- Добавлено событие "Каждый кадр" для всех визуальных компонентов. -- Добавлен новый компонент "Робот" для управления курсором, для ввода текста и для создания ботов. -- В диалоге для файлов добавлена возможно указать расширения для фильтрации. -- Исправлен редкий баг при удалении компонентов с формы, с сообщением "The node must have parent value". -- Исправлено, теперь если компонент отключен (enabled=false), его события "Выход за пределы" и "Уничтожения" не срабатывают. -- В JPHP добавлен класс `php\lib\fs` для более удобной работы с файловой системой. -- Оптимизировано открытие старых проектов, долгостроев, был необычный баг, который приводил у увеличению времени повторного открытия проектов. - -Patch-B ------------- -- Добавлена возможность менять местами (перетаскивать) табы открытых редакторов форм, модулей и т.д. -- Добавлена возможность использовать ранее созданный объект в конструкторе событий, тип "объект", значение "созданный объект". -- Исправлена работа события "Выбор элемента" у списка, оно не работало. -- Добавлена возможность изменять тип уже добавленного события в редакторе форм и модулей. -- Добавлена возможность манипулировать событиями в редакторе через контекстное меню (ПКМ). -- Добавлен диалог подтверждения при удалении событий в редакторе. -- Доработано контекстное меню в редакторе форм и модулей, исправлены редкие графический дефекты; пункты недоступны, если их невозможно применить к объекту. -- Доработано: теперь заблокированные объекты через редактор форм сохраняют свой статус блокировки после переоткрытия в редакторе. -- Исправлен баг, когда после изменения размеров формы в редакторе выделенные объекты сбрасывались. -- В диалоге открытия проекта список проектов из библиотеки был разделен на демо-проекты и проекты, который пользователь сохранил в библиотеку. -- Добавлены в UI элементы для открытия документации, но пока она в разработке. -- Доработано, теперь многие диалоги для файлов сохраняют ранее открытую папку. -- Доработано сохранение в библиотеку проектов, теперь среда запоминает нахождение проекта в библиотеке и не записывает его как новый при смене названия. - -Patch-A ------------- -- В библиотеку проектов добавлена простая игра "Арканоид". -- Появилась возможность добавлять клонов в редакторе (из других форм), см. вкладку "Прототипы" в панеле типов объектов. -- Добавлены новые глобальные события для клавиатуры всем объектам, события имеют немного другую логику работы, подходящую для игр. -- В редактор форм добавлена возможность настройки отображения сетки, а также новый вид сетки. -- В свойствах формы в редакторе добавлено свойство "Размеры (W, H)" для ручного изменения размеров формы. -- Добавлена поведение "Ограниченное перемещение", для ограничения перемещений объекта только в зоне видимости. -- Исправлен баг с событием столкновение, во многих случаях оно не работало. -- Исправлен баг с поведением "Курсорный объект", в некоторых случаях курсор смещался относительно оригинального. -- Доработано поведение "Курсорный объект", теперь объект следует за курсором и вне программы. -- Исправлен баг, который приводил к невозможности задать скорость объекту в событии клонирования. -- Исправлен баг с поведением "Перемещение по сетке", в некоторых случаях поведение выдавало ошибку. -- Доработано поведение "Перемещение по сетке", теперь перемещение стало более отзывчивым к нажатию клавиш. -- Исправлена работа действия "Создать клона", в некоторых случаях оно генерировало некорректный код. -- Исправлены баги события "Выход за пределы" для объектов внутри игровой комнаты. -- Увеличена скорость клонирования в 10-20 раз для игровых объектов и картинок. -- Сильно уменьшено потребление памяти в IDE при загрузке картинок, увелична скорость загрузки картинок в IDE. -- Исправлен баг с невозможностью удалить поведение у объекта в редакторе. -- Исправлен баг с сохранением и загрузкой некоторых свойств компонента "Контейнер". -- Исправлено несколько багов связанных с загрузкой сцены из другой формы. -- Исправлен баг в редакторе спрайтов, иногда, при перетаскивании кадров, спрайт генерировался в неверном порядке. -- Доработан диалог добавления поведений, теперь открытая вкладка запоминается и нет лага формирования табов. -- Исправлена работа действия "Если глобальная переменная..." в конструкторе событий. -- Исправлено повторное срабатывание события "Уничтожение". -- Исправлены многочисленные баги в действии "Отскочить". -- Немного оптимизирована загрузка среды. - -Alpha-3 (31.01.2016) ------------- -- Добавлен новый компонент "Игровая комната", компонент "Спрайтовый объект" переименован в "Игровой объект". -- Добавлена базавая физика для игр - эмуляция гравитации и скорости (см. поведения "Игровая сцена" и "Объект игровой сцены"). -- Добавлены новые игровые действия для перемещения, гравитации во вкладке "Игра". -- Добавлена возможность клонирования объектов во время выполнения программы (очень необходимо в играх). -- Добавлено игровое поведение "Возвращаемость" (вкладка "Игра") -- В редакторе спрайтов добавлена опция "Авторазмер". -- Добавлены события "Уничтожение", "Выход за пределы", "Столкновение" и "Клонирование". -- Добавлена возможность открывать исходный код форм и модулей во всю вкладку. -- Добавлен новый способ отображения списка действий в конструкторе событий (Иконки + текст) -- Оптимизирована и улучшена производительность конструктора событий и всей среды в общем. -- Переработан диалог открытия и создания проекта, добавлена вкладка "Библиотечные проекты" в диалоге открытия - -Patch-B ------------- -- Для удобства, теперь в исходный код события добавляется комментарий о том, есть ли в нем еще и заданные действия через конструктор. -- Исправлен баг с генерацией спрайтов, в некоторых случаях на спрайте возникали различные графические дефекты. -- Ипсравлен баг с зависанием редактора кода, в некоторых случаях он отображался, но был недоступен для редактирования. -- Доработана генерация php методов для событий, добавлено значение по умолчанию "= null". -- Исправлен баг с компонентом "Плоская кнопка", у компонента не работало свойство "Иконка" после запуска программы. -- Исправлен баг сборки приложений с ресурсами, в названии которых присутствовали не латинские буквы, например, из русского алфавита. -- Исправлен баг с компонентами, которые находились внутри компонента "Контейнер", не работали некоторые свойства, например "Иконка", "Изображение", "Доступность" и т.д. -- Добавлен в АПИ удобный способ доступа к поведениям объектов, например, $this->button->blinkAnim->disable() - blinkAnim объект поведения анимации "Мигание". - -Patch-A ------------- -- Доработано: исключена возможность одновременного открытия проекта из двух и более экземпляров IDE, это приводило к потере данных проекта -- Исправлено автоматическое открытие проектов с ресурса develnext.org, в редких случаях проект не открывался -- Исправлен критический баг связанный с загрузкой форм во время выполнения программы, в некоторых случаях загружались не все данные -- Добавлена возможность выбрать глобальную переменную в типе значения, в конструкторе событий, в диалогах действий (раньше была только переменная) -- Многие окна программы IDE стали сохранять свою позицию и размеры (в том числе и после рестарта среды). -- Пофиксено неприятное поведение среды при нажатии на ALT в среде, при нажатии на ALT выделялось главное меню, теперь этого нет -- Добавлена возможность изменять размеры диалогово окна, где пользователь выбирает иконку или изображение. -- Исправлено: в диалоге выбора изображения во вкладке "Поиск в проекте" не показывались изображения с расширениеми в верхнем регистре (например pic.JPG) -- Исправлено некорректное сохранение кода из конструктора событий, если там присутствовала конструкция function (...) use (...) -- Исправлен баг работы действия "Загрузить контент", в некоторых случаях возникала ошибка. -- Доработано закрытие проекта, теперь после закрытия среда автоматически останавливает запущенную программу проекта -- Исправлена ситуация, когда в редакторе кода при вызове диалогов "Найти" и "Заменить" среда зависала полностью -- Доработаны функции "Найти" и "Заменить" в редакторе кода, после отмены или скрытия диалога все что подсвечено (найденное) теперь скрывается -- Исправлено: не работало свойство "Шрифт" у компонентов "Поле для ввода" и "Многострочное поле". -- Исправлено: использование символа "%" в начале текста компонента приводило к ошибкам сборки и невозможности открыть форму в редакторе -- Доработана остановка программ, теперь она происходит в некоторых случаях быстрее -- Исправлена проблема когда в проекте есть синтаксические ошибки и после запуска процесс программы (java.exe) оставался висеть незавершенным - -09.01.2016 (alpha-2, included patch-a & patch-b) ------------- -Новое: -- Добавлены функции работы с аудио, новый компонент "Аудио плеер" и новые действия в конструкторе -- Добавлена возможность восстановления пароля (функция "Забыли пароль") -- Добавлена возможность обращаться к компонентам загрузчика (AppModule) из всех модулей и форм -- Добавлена функция "Поделиться проектом", которая позволяет выкладывать проект на develnext.org -- Добавлена функция автоматического открытия проектов по ссылке (см. пункт "поделиться проектом", необходимо скопировать ссылку в буфер обмена) -- Добавлен новый способ вывода списка компонентов без текста, только иконками (в редакторе форм и модулей) -- Переработан конструктор событий, теперь есть возможность менять php код прямо из конструктора событий -- Доработано: при удалении главной формы добавлено предложение выбрать новую главную форму -- Доработано: при добавлении первой формы в проект добавлено предложение сделать её главной в проекте -- Фиксы и доработки (см. ниже, patch-a и patch-b) - -- Фикс переоткрытия проекта с пустыми модулями из архива (в дереве проектов модули не показывались) -- Исправлено свойство "CSS класс(ы)", не сохранялись введенные значения -- Исправлен редкий недочет при регистрации и подтверждении почты (сообщение показывалось за окном и пользователь не видел его) -- Доработано удаление проектов в диалоге открытия проекта, добавлено диалоговое предупреждение "Вы уверены ..." -- Исправлен баг при удалении активного (открытого) проекта в диалоге открытия проекта, теперь проект будет автоматически закрываться -- Добавлена функция uiLater(), это клон метода UXApplication::runLater() для удобства -- Исправлен баг с компонентом "Изображение", при пустом значении после сборки показывалось сообщение "Cannot load image:" -- Исправлен баг в конструкторе действий в значениях с символом кавычки, если в значениях присутствовали кавычки это часто приводило к ошибке компиляции -- Исправлен баг с повторным отображением диалогов "Найти" и "Заменить" в редакторе кода, иногда диалоги не показывались - -Patch-B ------------- -- Добавлена функция "Поделиться проектом", которая позволяет выкладывать проект на develnext.org -- Добавлена функция автоматического открытия проектов по ссылке (см. пункт "поделиться проектом", необходимо скопировать ссылку в буфер обмена) -- Доработано создание и открытие проектов, теперь среда в случае не пустой папки предлагает перезаписать её или выбрать другую -- Доработан интерфейс диалогов самой среды (например диалог закрытия) -- Доработано: теперь кнопки и пункты меню IDE, которые работают только при открытом проекте, активны только при открытом проекте -- Обновлен вид отображения списка компонентов в редакторе форм и модулей (приближен к стилю DevelStudio) -- Добавлен новый способ вывода списка компонентов без текста, только иконками -- Добавлена возможность менять размеры панели действий в конструкторе событий (split pane) -- Доработано: главная форма среды теперь сохраняет позицию и размеры при последующих запусках -- Доработано: панель компонентов в редакторе теперь сохраняет открытые группы при переходе от формы к форме -- Исправлен недочет при закрытии среды без проекта в диалоге при выборе ответа "Нет" (среда никак не реагировала на этот вариант) -- Исправлен баг при копировании панельных компонентов вместе с объектами -- Исправлен редкий баг с кодировкой UTF-8 (например base64_decode для кириллицы выдавал некорректный результат) -- Исправлен баг при одновременном закрытии запущенной программы и нажатии на кнопку "остановить" выполнение программы -- Исправлен баг при конвертировании в код (в конструкторе событий), возникала некритичная ошибка -- Доработан запуск среды, теперь главная форма показывается после полной загрузки IDE -- Исправлен баг модульного компонента "Скрипт", не верно работали свойства "Одноразовый" и "Автозапуск", если оба были установлены в "Да" - -Patch-A -------------- -- Убрано лишнее оповещение об изменении псевдонима аккаунта -- Уменьшена форма изменения пароля -- Переработан конструктор событий, возможность менять php код прямо из конструктора событий -- Исправлены грамматические ошибки -- Исправлены баги с доступом к аккаунту в некоторых редких случаях -- Доработано: при удалении главной формы добавлено предложение выбрать новую главную форму -- Доработано: при добавлении первой формы в проект добавлено предложение сделать её главной в проекте -- Доработано: при создании форм/модулей с именем, которое уже используется в проекте, предлагается пересоздать форму/модуль -- Исправлено и доработана функция остановки программ -- Исправлен баг с невозможностью запустить программу из-за блокировок файлов и папок -- Доработан вывод ошибок в самой среде, теперь они выводяться в виде оповещений, а не диалогов -- Фикс свойства "Выравнивание" у компонентов полей (оно не работало после запуска программы) -- Полностью исправлена работа с компонентом "Контейнер" -- Исправлено закрытие диалога сохранения проекта в библиотеке через Alt+F4 -- Доработан поиск иконок, добавлен вывод автора иконки с лицензией (см. tooltip) и ссылкой -- Доработан интерфейс для Linux систем (на некоторых кнопках не помещался текст) -- Доработан вывод Splash Screen (в некоторых случаях он не отображался) -- Исправлен мелкий недочет в сборке JAR приложений: файл собирался с некорректным названием -- Исправлен баг с компонентом "Текст" и его свойством "иконка" (она не отображалась после запуска) -- Исправлен баг с компонентом "Текст", если у компонента стоял авторазмер и была загружена иконка, текст имел некорректные размеры -- Возможно пофиксен баг с выходом из FullScreen -- Пофиксен недочет с выводом псевдонима с символом "_" в меню IDE (этот символ не показывался) - -29.12.2015 (alpha-1) ------------- -*Новое* -- Интеграция онлайн сообщества (функции аккаунта) -- Диалог онлайн поиска иконок в базе сообщества (требуется авторизация) -- Новое действие "Если пароль верный" в конструкторе событий, вкладка "Условия" -- Новые действия для FullScreen режима в конструкторе событий, вкладка "Система" -- Новое анимационное поведение "Колебания" -- Новое поведение "Ограничение ввода" для компонентов полей -- Новый компонент Контейнер (ScrollBox) -- Новый модуль по-умолчанию "Загрузчик", который выполняется при старте программы -- Новые свойства у компонентов (всплывающая подсказка, css стиль, табуляция) -- Возможность выбрать главную форму проекта (вкладка "Проект") -- Возможность изменить название проекта (вкладка "Проект") -- Базовая возможность редактировать стиль проекта (вкладка "Проект" -> "CSS Стиль" в дереве проекта) -- Добавлено оповещение о выходе новых версий среды -- Добавлен "тип сообщения" в действии "Показать сообщение" (конструктор событий, вкладка "Управление") -- Приветствие при старте среды в виде аватара и имени пользователя (требуется авторизация) - -*Доработано* -- Поведению "Автоматическое уничтожение" добавлено свойство "анимировать" -- Доработана система автодоплнения - более продуманное скрытие подсказок -- Доработано UI диалога октрытия проекта -- Немного переработан интерфейс среды -- Исправлена работа анимационных поведений для форм, многие из них не работали -- В редакторе формы размеры самой формы теперь округляются до размеров сетки -- Исправлены различные баги отображения контекстного меню в редакторе формы -- Исправлены баги при сборке проектов с некоторыми нестандартными опциями -- Доработана функция остановки программы для некоторых нестандартных случаев - -16.11.2015 ------------- -- Новый компонент Flat Button (Плоская кнопка) -- Новый компонент Панель табов -- Новый компонент Панель -- Базовое автодополнение для $this->, $this->any-> и не только -- Анимационные поведения можно теперь навешивать на события наведения или клика (в свойствах) -- Библиотека проектов - можно сохранять проекты в библиотеке и использовать их как шаблоны при создании новых проектов -- Несколько демо-проектов в библиотеке проектов. -- Новые и улучшенные действия в конструкторе - для игрового счета и для более гибких условий -- Возможность задать жирность и наклонность тексту в диалоге выбора шрифта -- Добавлен инспектор объектов для форм и модулей -- Добавлено действие-условия для проверки пересечения двух объектов -- Исправлен баг выделения объектов в редакторе форм и модулей -- Исправлено позиционирование круга и овала после запуска программы -- Другие исправления и доработки - -02.11.2015 ------------- -- Спрайты и спрайтовые объекты (анимация с помощью набора кадров), новые действия для спрайтовой анимации в конструкторе событий -- Возвращено большое количество стандартных функци php (добавлено расширение jphp-zend-ext) -- Новое поведение "Таскание объекта" (drag-n-drop) -- Новое поведение "Перемещение по сетке" (поведение для игр, управление объектом с помощью стрелок) -- Новое поведение "Вращение" (анимация) -- Новое свойство "Авторазмер" для текстов -- Возможность выбрать изображение из ранее загруженных в проект -- Улучшен диалог загрузки изображения - система поиска дубликатов изображений в папке проекта -- Фикс: функции dump, alert, pre теперь доступны и после сборки проекта -- Фикс: некорректное поведение горячей клавишы Delete в редакторе форм и редакторе исходного кода -- Фикс: удаление большого количества объектов с формы иногда приводило к некорректному удалению кода событий -- Фикс: редактор кода под Linux теперь работает стабильнее -- Изменение: добавлена постоянная вкладка "Проект" с деревом ресурсов - -11.10.2015 ------------- -- Добавлена система поведений (behaviour) и набор из 7 базовых поведений (анимация, управление и логика) - - Поведение "Таскание формы" - чтобы с помощью объекта можно было таскать форму - - Поведение "Курсорный объект" - для того, чтобы заменить иконку курсора - - Поведения анимации "Мигание", "Дергание" и "Случайные перемещения" - - Поведение "ВременнОе табло" - для быстрой реализации функционала часов - - ... и другие -- Доработан компонент "Изображение" (добавлены новые свойства - авторазмер, растягивать, по центру, мозайка, отступы мозайки, текст) -- Добавлен компонент "Веб браузер" в базовой версии (возможны баги) -- Добавлено свойство "Растягивание" всем компонентам для более гибкого позиционирования UI элементов -- Добавлены новый действия в конструкторе событий для системы поведений (вкладка "Скрипт") -- Добавлена возможность делать формы полностью прозрачными, теперь можно делать окна любой формы (см. свойство "Стиль" у формы) -- Добавлена вкладка "Сгенерированный код" в конструктор событий, в ней можно сразу наблюдать генерируемый php код из собранных действий -- Немного переделан интерфейс среды, теперь список форм и модуле находятся в отдельной вкладке "Проект" (см. в левый нижний угол главной формы) -- Исправлены многочисленные баги с редактором кода, проявлялись они по разному: белый фон вместо редакторы, вылетающие ошибки и т.д. -- Исправлено открытие проектов из архивов Zip, множественные доработки -- Из редактора кода временно убран функционал автодополнения -- Многочисленые исправление багов, фиксы и мелкие доработки. - - -26.09.2015 ------------- -- Добавлены новые визуальные компоненты: поле для даты, круг, прямоугольник, овал, ромб и шестиугольник -- Добавлено свойство "Цвет фона" для форм -- Добавлен невизуальный компонент "Файл" для удобной работы с файлами и их содержимым -- Добавлен невизуальный компонент "Скрипт", похожий на компонент "Функция" из DevelStudio -- Новыйе действия - анимация, загрузка форм, изменение доступности объектов и другое -- Новое действие в условиях - "Если текст" - для проверки текста объектов разными способами -- Добавлено сохранение проекта в архив (zip) и загрузка из архива -- Улучшен редактор форм: возможность создавать компоненты на компонентах и другие мелкие улучшения -- Почти в два раза увеличена скорость повторного запуска и сборки программ -- В диалоге действий для выбора объектов добавлено более подробное отображение выбранного элемента с иконкой -- Действиям в конструкторе событий были добавлены значения по-умолчанию (в момент добавления действия) -- Оптимизировано открытие диалогов действий в конструкторе событий, теперь они открываются быстрее -- Фикс ошибки при открытии выбора шрифта в свойствах объекта -- Фикс ошибки в диалоге открытия проекта через кнопку "Обзор", если отсутствовала папка проектов возникала ошибка - -15.09.2015 ------------- -- Добавлен конструктор события как в GameMaker с возможностью конвертирования в php код -- Добавлено множество действий для конструктора событий -- Добавлены новые функции для работы с ОС -- Добавлен удобный диалог выбора компонентов в свойствах некоторых объектов -- Фикс выполнения событий компонентов, которые находятся в объекте типа "спойлер" -- Фикс открытия проектов в случае, если над проектом работал другой пользователь -- Мелкие багфиксы - -30.08.2015 ------------- -- Расширена система событий (новые подсобытия для мыши и клавиатуры) -- Добавлено событие прокрутки (скроллинга) -- Добавлены свойства "Непрозрачность" и "Угол наклона" для визуальных компонентов -- Добавлен компонент "Спойлер" (выпадающая панель) -- Исправлены ошибки в сборщиках проекта -- Фикс ошибки вылета из среды в моменты drag-n-drop в редакторе кода -- Различные фиксы и исправления - -16.08.2015 ------------- -- Добавлен визуальный компонент "Изображение" -- Добавлена возможность назначить иконку многим компонентам (кнопке, тексту, галочке) -- Доработан "Таймер": новое свойство "автостарт", исправлены некоторые баги -- Доработан визуальный компонент "Прогресс": теперь прогресс в процентах от 0 до 100 -- Добавлено свойство "Курсор" для всех компонентов -- Добавлено свойство "Иконка" для форм -- Добавлен кнопка "Скопировать" в редакторе свойств, например для свойств ID -- Доработаны модули: теперь есть возможность обращаться по ID к компонентам подключенных модулей из форм -- Добавлены свойства "автор", "описание" и "версия" для модулей -- Доработан редактор кода, исправлены многие ошибки -- Добавлено меню в редактор кода, возможность поиска и замены -- Добавлено базовое авто-дополнение кода в редактор кода -- Исправлено: удаление в редакторе модулей, глюки с некорректным удалением в редакторе форм -- Исправлены глюки редактора форм: некоторые компоненты не выделялись, теряли фокус выделения -- Добавлена иконка для DevelNext - -09.08.2015 ------------- -- Добавлена система модулей и скриптов, возможность привязать к форме несколько скриптов -- Добавлены скрипты: Таймер, Диалоги для файлов и папок -- Возможность удалить форму из проекта -- Расширено меню дереве проекта: пункты "удалить" и "открыть в проводнике" -- Добавлен UI компонент "Ползунок" (слайдер) -- Возможность безопастно менять ID компонентов в редакторе -- Расширены подсказки в редакторе свойств компонентов и скриптов (http://community.develstudio.ru/showthread.php/12597) -- Упрощено свойство модальность у форм в редакторе -- Фикс проблем с редактором кода (при запуске IDE) -- Фикс зависания при добавлении более 3х одинаковых объектов -- Фикс проблемы с кодировкой в редакторе событий -- Фикс сборки JAR файла для проектов с русскими названиями -- Мелкие фиксы и доработки в GUI библиотеке -- Мелкие доработки UI - -26.07.2015 ------------- -- Доработан сборщик windows приложений -- Возможность собирать приложение в один испольняемый файл -- Возможность собрать приложение в инсталятор одним файлом (InnoSetup) -- Возможность собрать кроссплатформенный JAR файл -- Добавлены всевозможные настройки для сборщиков проекта -- Новые компоненты: список, разделитель, выбор цвета, ссылка -- Фикс открытия сохраненных форм помимо главной формы -- Доработано открытие проекта: восстановление ранее открытых файлов -- Фикс запуска проектов с русскими названиями - -21.07.2015 ------------- -- Простой редактор событий -- Простой сборщик проектов для Windows -- Добавлены компоненты: выпадающий список, поле пароля, кнопка переключатель -- Возможность завершать программу из среды - -10.07.2015 ------------- -- Фиксы -- Новые свойства компонентов в редакторе -- Новые компоненты: прогресс, индикатор загрузки, многострочное поле -- Возможность добавить форму -- Возможность изменять настройки формы - -05.07.2015 ------------- -- Возможность запускать проекты -- Диалог закрытия проекта -- Welcome вкладка - -03.07.2015 -------------- -- Начало ведение истории проекта. -- Базовый функционал. +Patch-A +------------ +- Добавлена функция автоматического импорта классов use (включена по-умолчанию). +- Добавлена эксперементальная функция компилирования исходников в байткод (пока с сохранением дубликата исходников). +- Доработан вывод ошибок, теперь во всех случаях показывается корректный номер строки ошибки (добавлены sourcemap). +- Добавлено автодополнение для многих утилитных классов и их статичных методов, например, для классов str, fs и т.д. +- Исправлен баг с постоянной ошибкой ConcurrentException в среде. +- Переработана сборка программ, реализована базовая система пакетов (расширений) для проекта. +- Окно прогресса сборки проекта стало отображать процесс более точно. +- Исправлен лаг диалогов-вопросов в среде, было заметно, что они прыгают в центр экрана. + +Alpha-4 (21.02.2016) +------------ +*Основные фичи* ++ Система помощи, онлайн справка, F.A.Q. ++ Возможность добавлять клонов в редакторе, а не только во время выполнения. ++ Табы открытых редакторов теперь можно перетаскивать, менять местами. ++ Возможность легко сменить тип события, сохраняя его код и действия. ++ Новые события глобальной клавиатуры, с логикой работы как в играх. ++ Новое событие "Каждый кадр", которое отрабатывает каждый кадр существования объекта. ++ Новое игровое поведение - "Ограниченное перемещение". ++ В редакторе форм новая возможность настраивать способ отображения сетки для выравнивания объектов. ++ Новый демо-проект "Арканоид" для демонстрации игровых возможностей. ++ Множество мелких улучшений и доработок, см. ниже + патчи A и B. ++ Добавлено действие для сворачивания и разворачивания формы во вкладке объекты. + +- Добавлена система онлайн помощи, поиск по документации и сама документация с ответами на многие вопросы. +- Добавлено событие "Каждый кадр" для всех визуальных компонентов. +- Добавлен новый компонент "Робот" для управления курсором, для ввода текста и для создания ботов. +- В диалоге для файлов добавлена возможно указать расширения для фильтрации. +- Исправлен редкий баг при удалении компонентов с формы, с сообщением "The node must have parent value". +- Исправлено, теперь если компонент отключен (enabled=false), его события "Выход за пределы" и "Уничтожения" не срабатывают. +- В JPHP добавлен класс `php\lib\fs` для более удобной работы с файловой системой. +- Оптимизировано открытие старых проектов, долгостроев, был необычный баг, который приводил у увеличению времени повторного открытия проектов. + +Patch-B +------------ +- Добавлена возможность менять местами (перетаскивать) табы открытых редакторов форм, модулей и т.д. +- Добавлена возможность использовать ранее созданный объект в конструкторе событий, тип "объект", значение "созданный объект". +- Исправлена работа события "Выбор элемента" у списка, оно не работало. +- Добавлена возможность изменять тип уже добавленного события в редакторе форм и модулей. +- Добавлена возможность манипулировать событиями в редакторе через контекстное меню (ПКМ). +- Добавлен диалог подтверждения при удалении событий в редакторе. +- Доработано контекстное меню в редакторе форм и модулей, исправлены редкие графический дефекты; пункты недоступны, если их невозможно применить к объекту. +- Доработано: теперь заблокированные объекты через редактор форм сохраняют свой статус блокировки после переоткрытия в редакторе. +- Исправлен баг, когда после изменения размеров формы в редакторе выделенные объекты сбрасывались. +- В диалоге открытия проекта список проектов из библиотеки был разделен на демо-проекты и проекты, который пользователь сохранил в библиотеку. +- Добавлены в UI элементы для открытия документации, но пока она в разработке. +- Доработано, теперь многие диалоги для файлов сохраняют ранее открытую папку. +- Доработано сохранение в библиотеку проектов, теперь среда запоминает нахождение проекта в библиотеке и не записывает его как новый при смене названия. + +Patch-A +------------ +- В библиотеку проектов добавлена простая игра "Арканоид". +- Появилась возможность добавлять клонов в редакторе (из других форм), см. вкладку "Прототипы" в панеле типов объектов. +- Добавлены новые глобальные события для клавиатуры всем объектам, события имеют немного другую логику работы, подходящую для игр. +- В редактор форм добавлена возможность настройки отображения сетки, а также новый вид сетки. +- В свойствах формы в редакторе добавлено свойство "Размеры (W, H)" для ручного изменения размеров формы. +- Добавлена поведение "Ограниченное перемещение", для ограничения перемещений объекта только в зоне видимости. +- Исправлен баг с событием столкновение, во многих случаях оно не работало. +- Исправлен баг с поведением "Курсорный объект", в некоторых случаях курсор смещался относительно оригинального. +- Доработано поведение "Курсорный объект", теперь объект следует за курсором и вне программы. +- Исправлен баг, который приводил к невозможности задать скорость объекту в событии клонирования. +- Исправлен баг с поведением "Перемещение по сетке", в некоторых случаях поведение выдавало ошибку. +- Доработано поведение "Перемещение по сетке", теперь перемещение стало более отзывчивым к нажатию клавиш. +- Исправлена работа действия "Создать клона", в некоторых случаях оно генерировало некорректный код. +- Исправлены баги события "Выход за пределы" для объектов внутри игровой комнаты. +- Увеличена скорость клонирования в 10-20 раз для игровых объектов и картинок. +- Сильно уменьшено потребление памяти в IDE при загрузке картинок, увелична скорость загрузки картинок в IDE. +- Исправлен баг с невозможностью удалить поведение у объекта в редакторе. +- Исправлен баг с сохранением и загрузкой некоторых свойств компонента "Контейнер". +- Исправлено несколько багов связанных с загрузкой сцены из другой формы. +- Исправлен баг в редакторе спрайтов, иногда, при перетаскивании кадров, спрайт генерировался в неверном порядке. +- Доработан диалог добавления поведений, теперь открытая вкладка запоминается и нет лага формирования табов. +- Исправлена работа действия "Если глобальная переменная..." в конструкторе событий. +- Исправлено повторное срабатывание события "Уничтожение". +- Исправлены многочисленные баги в действии "Отскочить". +- Немного оптимизирована загрузка среды. + +Alpha-3 (31.01.2016) +------------ +- Добавлен новый компонент "Игровая комната", компонент "Спрайтовый объект" переименован в "Игровой объект". +- Добавлена базавая физика для игр - эмуляция гравитации и скорости (см. поведения "Игровая сцена" и "Объект игровой сцены"). +- Добавлены новые игровые действия для перемещения, гравитации во вкладке "Игра". +- Добавлена возможность клонирования объектов во время выполнения программы (очень необходимо в играх). +- Добавлено игровое поведение "Возвращаемость" (вкладка "Игра") +- В редакторе спрайтов добавлена опция "Авторазмер". +- Добавлены события "Уничтожение", "Выход за пределы", "Столкновение" и "Клонирование". +- Добавлена возможность открывать исходный код форм и модулей во всю вкладку. +- Добавлен новый способ отображения списка действий в конструкторе событий (Иконки + текст) +- Оптимизирована и улучшена производительность конструктора событий и всей среды в общем. +- Переработан диалог открытия и создания проекта, добавлена вкладка "Библиотечные проекты" в диалоге открытия + +Patch-B +------------ +- Для удобства, теперь в исходный код события добавляется комментарий о том, есть ли в нем еще и заданные действия через конструктор. +- Исправлен баг с генерацией спрайтов, в некоторых случаях на спрайте возникали различные графические дефекты. +- Ипсравлен баг с зависанием редактора кода, в некоторых случаях он отображался, но был недоступен для редактирования. +- Доработана генерация php методов для событий, добавлено значение по умолчанию "= null". +- Исправлен баг с компонентом "Плоская кнопка", у компонента не работало свойство "Иконка" после запуска программы. +- Исправлен баг сборки приложений с ресурсами, в названии которых присутствовали не латинские буквы, например, из русского алфавита. +- Исправлен баг с компонентами, которые находились внутри компонента "Контейнер", не работали некоторые свойства, например "Иконка", "Изображение", "Доступность" и т.д. +- Добавлен в АПИ удобный способ доступа к поведениям объектов, например, $this->button->blinkAnim->disable() - blinkAnim объект поведения анимации "Мигание". + +Patch-A +------------ +- Доработано: исключена возможность одновременного открытия проекта из двух и более экземпляров IDE, это приводило к потере данных проекта +- Исправлено автоматическое открытие проектов с ресурса develnext.org, в редких случаях проект не открывался +- Исправлен критический баг связанный с загрузкой форм во время выполнения программы, в некоторых случаях загружались не все данные +- Добавлена возможность выбрать глобальную переменную в типе значения, в конструкторе событий, в диалогах действий (раньше была только переменная) +- Многие окна программы IDE стали сохранять свою позицию и размеры (в том числе и после рестарта среды). +- Пофиксено неприятное поведение среды при нажатии на ALT в среде, при нажатии на ALT выделялось главное меню, теперь этого нет +- Добавлена возможность изменять размеры диалогово окна, где пользователь выбирает иконку или изображение. +- Исправлено: в диалоге выбора изображения во вкладке "Поиск в проекте" не показывались изображения с расширениеми в верхнем регистре (например pic.JPG) +- Исправлено некорректное сохранение кода из конструктора событий, если там присутствовала конструкция function (...) use (...) +- Исправлен баг работы действия "Загрузить контент", в некоторых случаях возникала ошибка. +- Доработано закрытие проекта, теперь после закрытия среда автоматически останавливает запущенную программу проекта +- Исправлена ситуация, когда в редакторе кода при вызове диалогов "Найти" и "Заменить" среда зависала полностью +- Доработаны функции "Найти" и "Заменить" в редакторе кода, после отмены или скрытия диалога все что подсвечено (найденное) теперь скрывается +- Исправлено: не работало свойство "Шрифт" у компонентов "Поле для ввода" и "Многострочное поле". +- Исправлено: использование символа "%" в начале текста компонента приводило к ошибкам сборки и невозможности открыть форму в редакторе +- Доработана остановка программ, теперь она происходит в некоторых случаях быстрее +- Исправлена проблема когда в проекте есть синтаксические ошибки и после запуска процесс программы (java.exe) оставался висеть незавершенным + +09.01.2016 (alpha-2, included patch-a & patch-b) +------------ +Новое: +- Добавлены функции работы с аудио, новый компонент "Аудио плеер" и новые действия в конструкторе +- Добавлена возможность восстановления пароля (функция "Забыли пароль") +- Добавлена возможность обращаться к компонентам загрузчика (AppModule) из всех модулей и форм +- Добавлена функция "Поделиться проектом", которая позволяет выкладывать проект на develnext.org +- Добавлена функция автоматического открытия проектов по ссылке (см. пункт "поделиться проектом", необходимо скопировать ссылку в буфер обмена) +- Добавлен новый способ вывода списка компонентов без текста, только иконками (в редакторе форм и модулей) +- Переработан конструктор событий, теперь есть возможность менять php код прямо из конструктора событий +- Доработано: при удалении главной формы добавлено предложение выбрать новую главную форму +- Доработано: при добавлении первой формы в проект добавлено предложение сделать её главной в проекте +- Фиксы и доработки (см. ниже, patch-a и patch-b) + +- Фикс переоткрытия проекта с пустыми модулями из архива (в дереве проектов модули не показывались) +- Исправлено свойство "CSS класс(ы)", не сохранялись введенные значения +- Исправлен редкий недочет при регистрации и подтверждении почты (сообщение показывалось за окном и пользователь не видел его) +- Доработано удаление проектов в диалоге открытия проекта, добавлено диалоговое предупреждение "Вы уверены ..." +- Исправлен баг при удалении активного (открытого) проекта в диалоге открытия проекта, теперь проект будет автоматически закрываться +- Добавлена функция uiLater(), это клон метода UXApplication::runLater() для удобства +- Исправлен баг с компонентом "Изображение", при пустом значении после сборки показывалось сообщение "Cannot load image:" +- Исправлен баг в конструкторе действий в значениях с символом кавычки, если в значениях присутствовали кавычки это часто приводило к ошибке компиляции +- Исправлен баг с повторным отображением диалогов "Найти" и "Заменить" в редакторе кода, иногда диалоги не показывались + +Patch-B +------------ +- Добавлена функция "Поделиться проектом", которая позволяет выкладывать проект на develnext.org +- Добавлена функция автоматического открытия проектов по ссылке (см. пункт "поделиться проектом", необходимо скопировать ссылку в буфер обмена) +- Доработано создание и открытие проектов, теперь среда в случае не пустой папки предлагает перезаписать её или выбрать другую +- Доработан интерфейс диалогов самой среды (например диалог закрытия) +- Доработано: теперь кнопки и пункты меню IDE, которые работают только при открытом проекте, активны только при открытом проекте +- Обновлен вид отображения списка компонентов в редакторе форм и модулей (приближен к стилю DevelStudio) +- Добавлен новый способ вывода списка компонентов без текста, только иконками +- Добавлена возможность менять размеры панели действий в конструкторе событий (split pane) +- Доработано: главная форма среды теперь сохраняет позицию и размеры при последующих запусках +- Доработано: панель компонентов в редакторе теперь сохраняет открытые группы при переходе от формы к форме +- Исправлен недочет при закрытии среды без проекта в диалоге при выборе ответа "Нет" (среда никак не реагировала на этот вариант) +- Исправлен баг при копировании панельных компонентов вместе с объектами +- Исправлен редкий баг с кодировкой UTF-8 (например base64_decode для кириллицы выдавал некорректный результат) +- Исправлен баг при одновременном закрытии запущенной программы и нажатии на кнопку "остановить" выполнение программы +- Исправлен баг при конвертировании в код (в конструкторе событий), возникала некритичная ошибка +- Доработан запуск среды, теперь главная форма показывается после полной загрузки IDE +- Исправлен баг модульного компонента "Скрипт", не верно работали свойства "Одноразовый" и "Автозапуск", если оба были установлены в "Да" + +Patch-A +------------- +- Убрано лишнее оповещение об изменении псевдонима аккаунта +- Уменьшена форма изменения пароля +- Переработан конструктор событий, возможность менять php код прямо из конструктора событий +- Исправлены грамматические ошибки +- Исправлены баги с доступом к аккаунту в некоторых редких случаях +- Доработано: при удалении главной формы добавлено предложение выбрать новую главную форму +- Доработано: при добавлении первой формы в проект добавлено предложение сделать её главной в проекте +- Доработано: при создании форм/модулей с именем, которое уже используется в проекте, предлагается пересоздать форму/модуль +- Исправлено и доработана функция остановки программ +- Исправлен баг с невозможностью запустить программу из-за блокировок файлов и папок +- Доработан вывод ошибок в самой среде, теперь они выводяться в виде оповещений, а не диалогов +- Фикс свойства "Выравнивание" у компонентов полей (оно не работало после запуска программы) +- Полностью исправлена работа с компонентом "Контейнер" +- Исправлено закрытие диалога сохранения проекта в библиотеке через Alt+F4 +- Доработан поиск иконок, добавлен вывод автора иконки с лицензией (см. tooltip) и ссылкой +- Доработан интерфейс для Linux систем (на некоторых кнопках не помещался текст) +- Доработан вывод Splash Screen (в некоторых случаях он не отображался) +- Исправлен мелкий недочет в сборке JAR приложений: файл собирался с некорректным названием +- Исправлен баг с компонентом "Текст" и его свойством "иконка" (она не отображалась после запуска) +- Исправлен баг с компонентом "Текст", если у компонента стоял авторазмер и была загружена иконка, текст имел некорректные размеры +- Возможно пофиксен баг с выходом из FullScreen +- Пофиксен недочет с выводом псевдонима с символом "_" в меню IDE (этот символ не показывался) + +29.12.2015 (alpha-1) +------------ +*Новое* +- Интеграция онлайн сообщества (функции аккаунта) +- Диалог онлайн поиска иконок в базе сообщества (требуется авторизация) +- Новое действие "Если пароль верный" в конструкторе событий, вкладка "Условия" +- Новые действия для FullScreen режима в конструкторе событий, вкладка "Система" +- Новое анимационное поведение "Колебания" +- Новое поведение "Ограничение ввода" для компонентов полей +- Новый компонент Контейнер (ScrollBox) +- Новый модуль по-умолчанию "Загрузчик", который выполняется при старте программы +- Новые свойства у компонентов (всплывающая подсказка, css стиль, табуляция) +- Возможность выбрать главную форму проекта (вкладка "Проект") +- Возможность изменить название проекта (вкладка "Проект") +- Базовая возможность редактировать стиль проекта (вкладка "Проект" -> "CSS Стиль" в дереве проекта) +- Добавлено оповещение о выходе новых версий среды +- Добавлен "тип сообщения" в действии "Показать сообщение" (конструктор событий, вкладка "Управление") +- Приветствие при старте среды в виде аватара и имени пользователя (требуется авторизация) + +*Доработано* +- Поведению "Автоматическое уничтожение" добавлено свойство "анимировать" +- Доработана система автодоплнения - более продуманное скрытие подсказок +- Доработано UI диалога октрытия проекта +- Немного переработан интерфейс среды +- Исправлена работа анимационных поведений для форм, многие из них не работали +- В редакторе формы размеры самой формы теперь округляются до размеров сетки +- Исправлены различные баги отображения контекстного меню в редакторе формы +- Исправлены баги при сборке проектов с некоторыми нестандартными опциями +- Доработана функция остановки программы для некоторых нестандартных случаев + +16.11.2015 +------------ +- Новый компонент Flat Button (Плоская кнопка) +- Новый компонент Панель табов +- Новый компонент Панель +- Базовое автодополнение для $this->, $this->any-> и не только +- Анимационные поведения можно теперь навешивать на события наведения или клика (в свойствах) +- Библиотека проектов - можно сохранять проекты в библиотеке и использовать их как шаблоны при создании новых проектов +- Несколько демо-проектов в библиотеке проектов. +- Новые и улучшенные действия в конструкторе - для игрового счета и для более гибких условий +- Возможность задать жирность и наклонность тексту в диалоге выбора шрифта +- Добавлен инспектор объектов для форм и модулей +- Добавлено действие-условия для проверки пересечения двух объектов +- Исправлен баг выделения объектов в редакторе форм и модулей +- Исправлено позиционирование круга и овала после запуска программы +- Другие исправления и доработки + +02.11.2015 +------------ +- Спрайты и спрайтовые объекты (анимация с помощью набора кадров), новые действия для спрайтовой анимации в конструкторе событий +- Возвращено большое количество стандартных функци php (добавлено расширение jphp-zend-ext) +- Новое поведение "Таскание объекта" (drag-n-drop) +- Новое поведение "Перемещение по сетке" (поведение для игр, управление объектом с помощью стрелок) +- Новое поведение "Вращение" (анимация) +- Новое свойство "Авторазмер" для текстов +- Возможность выбрать изображение из ранее загруженных в проект +- Улучшен диалог загрузки изображения - система поиска дубликатов изображений в папке проекта +- Фикс: функции dump, alert, pre теперь доступны и после сборки проекта +- Фикс: некорректное поведение горячей клавишы Delete в редакторе форм и редакторе исходного кода +- Фикс: удаление большого количества объектов с формы иногда приводило к некорректному удалению кода событий +- Фикс: редактор кода под Linux теперь работает стабильнее +- Изменение: добавлена постоянная вкладка "Проект" с деревом ресурсов + +11.10.2015 +------------ +- Добавлена система поведений (behaviour) и набор из 7 базовых поведений (анимация, управление и логика) + - Поведение "Таскание формы" - чтобы с помощью объекта можно было таскать форму + - Поведение "Курсорный объект" - для того, чтобы заменить иконку курсора + - Поведения анимации "Мигание", "Дергание" и "Случайные перемещения" + - Поведение "ВременнОе табло" - для быстрой реализации функционала часов + - ... и другие +- Доработан компонент "Изображение" (добавлены новые свойства - авторазмер, растягивать, по центру, мозайка, отступы мозайки, текст) +- Добавлен компонент "Веб браузер" в базовой версии (возможны баги) +- Добавлено свойство "Растягивание" всем компонентам для более гибкого позиционирования UI элементов +- Добавлены новый действия в конструкторе событий для системы поведений (вкладка "Скрипт") +- Добавлена возможность делать формы полностью прозрачными, теперь можно делать окна любой формы (см. свойство "Стиль" у формы) +- Добавлена вкладка "Сгенерированный код" в конструктор событий, в ней можно сразу наблюдать генерируемый php код из собранных действий +- Немного переделан интерфейс среды, теперь список форм и модуле находятся в отдельной вкладке "Проект" (см. в левый нижний угол главной формы) +- Исправлены многочисленные баги с редактором кода, проявлялись они по разному: белый фон вместо редакторы, вылетающие ошибки и т.д. +- Исправлено открытие проектов из архивов Zip, множественные доработки +- Из редактора кода временно убран функционал автодополнения +- Многочисленые исправление багов, фиксы и мелкие доработки. + + +26.09.2015 +------------ +- Добавлены новые визуальные компоненты: поле для даты, круг, прямоугольник, овал, ромб и шестиугольник +- Добавлено свойство "Цвет фона" для форм +- Добавлен невизуальный компонент "Файл" для удобной работы с файлами и их содержимым +- Добавлен невизуальный компонент "Скрипт", похожий на компонент "Функция" из DevelStudio +- Новыйе действия - анимация, загрузка форм, изменение доступности объектов и другое +- Новое действие в условиях - "Если текст" - для проверки текста объектов разными способами +- Добавлено сохранение проекта в архив (zip) и загрузка из архива +- Улучшен редактор форм: возможность создавать компоненты на компонентах и другие мелкие улучшения +- Почти в два раза увеличена скорость повторного запуска и сборки программ +- В диалоге действий для выбора объектов добавлено более подробное отображение выбранного элемента с иконкой +- Действиям в конструкторе событий были добавлены значения по-умолчанию (в момент добавления действия) +- Оптимизировано открытие диалогов действий в конструкторе событий, теперь они открываются быстрее +- Фикс ошибки при открытии выбора шрифта в свойствах объекта +- Фикс ошибки в диалоге открытия проекта через кнопку "Обзор", если отсутствовала папка проектов возникала ошибка + +15.09.2015 +------------ +- Добавлен конструктор события как в GameMaker с возможностью конвертирования в php код +- Добавлено множество действий для конструктора событий +- Добавлены новые функции для работы с ОС +- Добавлен удобный диалог выбора компонентов в свойствах некоторых объектов +- Фикс выполнения событий компонентов, которые находятся в объекте типа "спойлер" +- Фикс открытия проектов в случае, если над проектом работал другой пользователь +- Мелкие багфиксы + +30.08.2015 +------------ +- Расширена система событий (новые подсобытия для мыши и клавиатуры) +- Добавлено событие прокрутки (скроллинга) +- Добавлены свойства "Непрозрачность" и "Угол наклона" для визуальных компонентов +- Добавлен компонент "Спойлер" (выпадающая панель) +- Исправлены ошибки в сборщиках проекта +- Фикс ошибки вылета из среды в моменты drag-n-drop в редакторе кода +- Различные фиксы и исправления + +16.08.2015 +------------ +- Добавлен визуальный компонент "Изображение" +- Добавлена возможность назначить иконку многим компонентам (кнопке, тексту, галочке) +- Доработан "Таймер": новое свойство "автостарт", исправлены некоторые баги +- Доработан визуальный компонент "Прогресс": теперь прогресс в процентах от 0 до 100 +- Добавлено свойство "Курсор" для всех компонентов +- Добавлено свойство "Иконка" для форм +- Добавлен кнопка "Скопировать" в редакторе свойств, например для свойств ID +- Доработаны модули: теперь есть возможность обращаться по ID к компонентам подключенных модулей из форм +- Добавлены свойства "автор", "описание" и "версия" для модулей +- Доработан редактор кода, исправлены многие ошибки +- Добавлено меню в редактор кода, возможность поиска и замены +- Добавлено базовое авто-дополнение кода в редактор кода +- Исправлено: удаление в редакторе модулей, глюки с некорректным удалением в редакторе форм +- Исправлены глюки редактора форм: некоторые компоненты не выделялись, теряли фокус выделения +- Добавлена иконка для DevelNext + +09.08.2015 +------------ +- Добавлена система модулей и скриптов, возможность привязать к форме несколько скриптов +- Добавлены скрипты: Таймер, Диалоги для файлов и папок +- Возможность удалить форму из проекта +- Расширено меню дереве проекта: пункты "удалить" и "открыть в проводнике" +- Добавлен UI компонент "Ползунок" (слайдер) +- Возможность безопастно менять ID компонентов в редакторе +- Расширены подсказки в редакторе свойств компонентов и скриптов (http://community.develstudio.ru/showthread.php/12597) +- Упрощено свойство модальность у форм в редакторе +- Фикс проблем с редактором кода (при запуске IDE) +- Фикс зависания при добавлении более 3х одинаковых объектов +- Фикс проблемы с кодировкой в редакторе событий +- Фикс сборки JAR файла для проектов с русскими названиями +- Мелкие фиксы и доработки в GUI библиотеке +- Мелкие доработки UI + +26.07.2015 +------------ +- Доработан сборщик windows приложений +- Возможность собирать приложение в один испольняемый файл +- Возможность собрать приложение в инсталятор одним файлом (InnoSetup) +- Возможность собрать кроссплатформенный JAR файл +- Добавлены всевозможные настройки для сборщиков проекта +- Новые компоненты: список, разделитель, выбор цвета, ссылка +- Фикс открытия сохраненных форм помимо главной формы +- Доработано открытие проекта: восстановление ранее открытых файлов +- Фикс запуска проектов с русскими названиями + +21.07.2015 +------------ +- Простой редактор событий +- Простой сборщик проектов для Windows +- Добавлены компоненты: выпадающий список, поле пароля, кнопка переключатель +- Возможность завершать программу из среды + +10.07.2015 +------------ +- Фиксы +- Новые свойства компонентов в редакторе +- Новые компоненты: прогресс, индикатор загрузки, многострочное поле +- Возможность добавить форму +- Возможность изменять настройки формы + +05.07.2015 +------------ +- Возможность запускать проекты +- Диалог закрытия проекта +- Welcome вкладка + +03.07.2015 +------------- +- Начало ведение истории проекта. +- Базовый функционал. diff --git a/develnext/src/.data/vendor/ide.bundle.std.JPHPDesktopDebugBundle/preloader.php b/develnext/src/.data/vendor/ide.bundle.std.JPHPDesktopDebugBundle/preloader.php index a4c21e7c..82b777b2 100644 --- a/develnext/src/.data/vendor/ide.bundle.std.JPHPDesktopDebugBundle/preloader.php +++ b/develnext/src/.data/vendor/ide.bundle.std.JPHPDesktopDebugBundle/preloader.php @@ -1,7 +1,13 @@ tryLoadSourceMap($filename); + } + } + + public function tryLoadSourceMap($filename) + { + $sourceMapFile = $filename . ".sourcemap"; + + if (Stream::exists($sourceMapFile)) { + $map = (array) Json::fromFile($sourceMapFile); + + if ($map) { + $sourceMap = new SourceMap($filename); + + foreach ($map as $cLine => $sLine) { + $sourceMap->addLine($sLine, $cLine); + } + + Environment::current()->registerSourceMap($sourceMap); + } + } + } +} + +$debugClassLoader = new DebugClassLoader(); +$debugClassLoader->register(true); \ No newline at end of file diff --git a/develnext/src/.system/application.conf b/develnext/src/.system/application.conf index 76928999..4d57fea7 100644 --- a/develnext/src/.system/application.conf +++ b/develnext/src/.system/application.conf @@ -1,13 +1,13 @@ -# MAIN CONFIGURATION - -app.name = DevelNext -app.version = 4.0 alpha-4 -app.hash = 2016022112 - -# APP -app.namespace = ide -app.mainForm = MainForm -app.showMainForm = 1 - -app.icon = .data/img/DevelNextIco.png - +# MAIN CONFIGURATION + +app.name = DevelNext +app.version = 4.0 alpha-4 (patched-a) +app.hash = 2016022112 + +# APP +app.namespace = ide +app.mainForm = MainForm +app.showMainForm = 1 + +app.icon = .data/img/DevelNextIco.png + diff --git a/develnext/src/JPHP-INF/.bootstrap.php b/develnext/src/JPHP-INF/.bootstrap.php index 7e5e631f..8b66c78f 100644 --- a/develnext/src/JPHP-INF/.bootstrap.php +++ b/develnext/src/JPHP-INF/.bootstrap.php @@ -7,8 +7,11 @@ use ide\systems\IdeSystem; use php\gui\UXDialog; +$cache = !IdeSystem::isDevelopment(); -$loader = new IdeClassLoader(!IdeSystem::isDevelopment(), IdeSystem::getOwnLibVersion()); +$cache = false; // TODO delete it. + +$loader = new IdeClassLoader($cache, IdeSystem::getOwnLibVersion()); $loader->register(true); diff --git a/develnext/src/ide/action/ActionManager.php b/develnext/src/ide/action/ActionManager.php index 9f08b0a5..9eb05e60 100644 --- a/develnext/src/ide/action/ActionManager.php +++ b/develnext/src/ide/action/ActionManager.php @@ -40,22 +40,26 @@ function __construct() /** * @param $directory * @param callable $log + * @param bool $withSourceMap */ - public function compile($directory, callable $log = null) + public function compile($directory, callable $log = null, $withSourceMap = false) { - FileUtils::scan($directory, function ($filename) use ($log) { + FileUtils::scan($directory, function ($filename) use ($log, $withSourceMap) { if (Str::equalsIgnoreCase(FileUtils::getExtension($filename), 'source')) { $phpFile = FileUtils::stripExtension($filename); $actionFile = $phpFile . '.axml'; - FileUtils::copyFile($filename, $phpFile); + if (!fs::exists($phpFile)) { + FileUtils::copyFile($filename, $phpFile); + } if (fs::exists($actionFile)) { $script = new ActionScript(null, $this); $script->load($actionFile); - $script->compile($filename, $phpFile); - if ($log) { + $count = $script->compile($filename, $phpFile, $withSourceMap); + + if ($log && $count) { $log($phpFile); } } diff --git a/develnext/src/ide/action/ActionScript.php b/develnext/src/ide/action/ActionScript.php index 9967defd..57cd6334 100644 --- a/develnext/src/ide/action/ActionScript.php +++ b/develnext/src/ide/action/ActionScript.php @@ -4,6 +4,7 @@ use ide\utils\Json; use ide\utils\PhpParser; use php\format\ProcessorException; +use php\lib\fs; use php\lib\Items; use php\lib\Str; use php\util\Flow; @@ -224,13 +225,19 @@ public function getImports(array $actions) return $imports->withKeys()->toArray(); } - public function compile($file, $outputFile = null) + public function compile($file, $outputFile = null, $withSourceMap = false) { if (!$outputFile) { $outputFile = $file; } - $phpParser = new PhpParser(FileUtils::get($file)); + $count = 0; + + $phpParser = PhpParser::ofFile(fs::exists($outputFile) ? $outputFile : $file, $withSourceMap); + + if ($withSourceMap) { + $phpParser->applySourceMapFile($outputFile . '.sourcemap'); + } $imports = Flow::of([]); @@ -245,6 +252,8 @@ public function compile($file, $outputFile = null) $actions = []; foreach ($domMethod->findAll('*') as $domAction) { + $count += 1; + $action = $this->manager->buildAction($domAction); $action->setContextClass($className); $action->setContextMethod($methodName); @@ -266,7 +275,7 @@ public function compile($file, $outputFile = null) $phpParser->addUseImports($imports); } - FileUtils::put($outputFile, $phpParser->getContent()); - Json::toFile($outputFile . '.sourcemap', $phpParser->getSourceMap()->toArray()); + $phpParser->saveContent($outputFile, $withSourceMap); + return $count; } } \ No newline at end of file diff --git a/develnext/src/ide/build/OneJarBuildType.php b/develnext/src/ide/build/OneJarBuildType.php index acab1caa..6cc299f4 100644 --- a/develnext/src/ide/build/OneJarBuildType.php +++ b/develnext/src/ide/build/OneJarBuildType.php @@ -8,6 +8,7 @@ use ide\misc\GradleBuildConfig; use ide\project\behaviours\GradleProjectBehaviour; use ide\project\Project; +use ide\systems\ProjectSystem; use ide\ui\Notifications; use php\gui\UXApplication; use php\io\File; @@ -97,6 +98,8 @@ static function appendJarTasks(GradleBuildConfig $config, $oneJar = true) exclude('.debug/**') exclude('**/*.source') exclude('**/*.sourcemap') + exclude('**/*.axml') + exclude('JPHP-INF/sdk/**') $code }\n"); @@ -119,23 +122,21 @@ function onExecute(Project $project, $finished = true) $config = $this->getConfig(); - $project->preCompile(Project::ENV_PROD); - - $process = new Process([$ide->getGradleProgram(), 'clean', 'splitConfig', 'jar'], $project->getRootDir(), $ide->makeEnvironment()); - $project->compile(Project::ENV_PROD); + $dialog = new BuildProgressForm(); + $dialog->show(); - /** @var GradleProjectBehaviour $gradle */ - $gradle = $project->getBehaviour(GradleProjectBehaviour::class); + ProjectSystem::compileAll(Project::ENV_PROD, $dialog, 'gradle jar', function () use ($ide, $project, $dialog) { + $process = new Process([$ide->getGradleProgram(), 'clean', 'splitConfig', 'jar'], $project->getRootDir(), $ide->makeEnvironment()); - self::appendJarTasks($gradle->getConfig()); + /** @var GradleProjectBehaviour $gradle */ + $gradle = $project->getBehaviour(GradleProjectBehaviour::class); - $dialog = new BuildProgressForm(); - $dialog->addConsoleLine('> gradle jar', 'green'); - $dialog->addConsoleLine(' --> ' . $project->getRootDir() . ' ..', 'gray'); + self::appendJarTasks($gradle->getConfig()); - $process = $process->start(); + $process = $process->start(); - $dialog->show($process); + $dialog->watchProcess($process); + }); $dialog->setOnExitProcess(function ($exitValue) use ($project, $dialog, $finished, $config) { Logger::info("Finish executing: exitValue = $exitValue"); diff --git a/develnext/src/ide/build/WindowsApplicationBuildType.php b/develnext/src/ide/build/WindowsApplicationBuildType.php index 81a26322..876c1b40 100644 --- a/develnext/src/ide/build/WindowsApplicationBuildType.php +++ b/develnext/src/ide/build/WindowsApplicationBuildType.php @@ -10,6 +10,7 @@ use ide\project\behaviours\GradleProjectBehaviour; use ide\project\behaviours\GuiFrameworkProjectBehaviour; use ide\project\Project; +use ide\systems\ProjectSystem; use ide\utils\FileUtils; use php\gui\event\UXEvent; use php\gui\UXAlert; @@ -192,51 +193,47 @@ function onExecute(Project $project, $finished = true) $config = $this->getConfig(); - $commands = [$ide->getGradleProgram(), 'clean']; - - if ($config['oneJar']) { - $commands[] = 'splitConfig'; - $commands[] = 'jar'; - } - - $commands[] = 'installDist'; + $dialog = new BuildProgressForm(); + $dialog->show(); - $project->preCompile(Project::ENV_PROD); - $process = new Process($commands, $project->getRootDir(), $ide->makeEnvironment()); - $project->compile(Project::ENV_PROD); + ProjectSystem::compileAll(Project::ENV_PROD, $dialog, 'gradle installDist', function () use ($ide, $project, $dialog, $config) { + $commands = [$ide->getGradleProgram(), 'clean']; - /** @var GradleProjectBehaviour $gradle */ - $gradle = $project->getBehaviour(GradleProjectBehaviour::class); + if ($config['oneJar']) { + $commands[] = 'splitConfig'; + $commands[] = 'jar'; + } - OneJarBuildType::appendJarTasks($gradle->getConfig(), $config['oneJar']); + $commands[] = 'installDist'; - $dialog = new BuildProgressForm(); - $dialog->addConsoleLine('> gradle installDist', 'green'); - $dialog->addConsoleLine(' --> ' . $project->getRootDir() . ' ..', 'gray'); + /** @var GradleProjectBehaviour $gradle */ + $gradle = $project->getBehaviour(GradleProjectBehaviour::class); - $process = $process->start(); + OneJarBuildType::appendJarTasks($gradle->getConfig(), $config['oneJar']); - $dialog->show(); + $process = new Process($commands, $project->getRootDir(), $ide->makeEnvironment()); + $process = $process->start(); - $dialog->watch([ - $process, - function () use ($project, $config) { - FileUtils::deleteDirectory($this->getBuildPath($project) . "/bin"); - $libPath = File::of($this->getBuildPath($project) . "/lib"); + $dialog->watch([ + $process, + function () use ($project, $config) { + FileUtils::deleteDirectory($this->getBuildPath($project) . "/bin"); + $libPath = File::of($this->getBuildPath($project) . "/lib"); - if ($config['oneJar']) { - FileUtils::scan($libPath, function ($filename) { - $file = File::of($filename); + if ($config['oneJar']) { + FileUtils::scan($libPath, function ($filename) { + $file = File::of($filename); - if (!Str::startsWith($file->getName(), "dn-compile")) { - $file->delete(); - } - }); - } + if (!Str::startsWith($file->getName(), "dn-compile")) { + $file->delete(); + } + }); + } - return $this->makeExecutableFile($project); - }, - ]); + return $this->makeExecutableFile($project); + }, + ]); + }); $dialog->setOnExitProcess(function ($exitValue) use ($project, $dialog, $finished, $config) { $configPath = $this->getLaunch4jConfigPath($project); diff --git a/develnext/src/ide/bundle/std/JPHPGuiDesktopBundle.php b/develnext/src/ide/bundle/std/JPHPGuiDesktopBundle.php index 25750841..d6ae4860 100644 --- a/develnext/src/ide/bundle/std/JPHPGuiDesktopBundle.php +++ b/develnext/src/ide/bundle/std/JPHPGuiDesktopBundle.php @@ -85,7 +85,7 @@ class JPHPGuiDesktopBundle extends AbstractJarBundle { function getName() { - return "JPHP Gui Desktop"; + return "JPHP UI Desktop"; } public function getDependencies() diff --git a/develnext/src/ide/commands/ExecuteProjectCommand.php b/develnext/src/ide/commands/ExecuteProjectCommand.php index e23f29a1..6030bc8b 100644 --- a/develnext/src/ide/commands/ExecuteProjectCommand.php +++ b/develnext/src/ide/commands/ExecuteProjectCommand.php @@ -8,6 +8,8 @@ use ide\Logger; use ide\misc\AbstractCommand; use ide\project\Project; +use ide\project\ProjectConsoleOutput; +use ide\systems\ProjectSystem; use ide\ui\Notifications; use ide\utils\FileUtils; use php\gui\event\UXEvent; @@ -154,32 +156,6 @@ public function onStopExecute(UXEvent $e = null, callable $callback = null) } } - public function prepareExecute(Project $project, BuildProgressForm $dialog, callable $callback) - { - $th = new Thread(function () use ($project, $dialog, $callback) { - $project->preCompile(Project::ENV_DEV, function ($log) use ($dialog) { - uiLater(function () use ($dialog, $log) { - $dialog->addConsoleLine($log, 'gray'); - }); - }); - - uiLater(function () use ($dialog, $project) { - $dialog->addConsoleLine('> gradle run', 'green'); - $dialog->addConsoleLine(' --> ' . $project->getRootDir() . ' ..', 'gray'); - }); - - $project->compile(Project::ENV_DEV, function ($log) use ($dialog) { - uiLater(function () use ($dialog, $log) { - $dialog->addConsoleLine($log, 'blue'); - }); - }); - - uiLater($callback); - }); - - $th->start(); - } - public function onExecute($e = null, AbstractEditor $editor = null) { $ide = Ide::get(); @@ -203,7 +179,7 @@ public function onExecute($e = null, AbstractEditor $editor = null) $this->startButton->enabled = false; $this->stopButton->enabled = true; - $this->prepareExecute($project, $dialog, function () use ($dialog) { + ProjectSystem::compileAll(Project::ENV_DEV, $dialog, 'gradle run', function () use ($dialog) { try { $this->process = $this->process->start(); $dialog->watchProcess($this->process); diff --git a/develnext/src/ide/forms/BuildProgressForm.php b/develnext/src/ide/forms/BuildProgressForm.php index 677a050d..1e620cd3 100644 --- a/develnext/src/ide/forms/BuildProgressForm.php +++ b/develnext/src/ide/forms/BuildProgressForm.php @@ -3,6 +3,7 @@ use ide\forms\mixins\SavableFormMixin; use ide\Ide; +use ide\project\ProjectConsoleOutput; use php\gui\event\UXEvent; use php\gui\event\UXMouseEvent; use php\gui\event\UXWindowEvent; @@ -32,7 +33,7 @@ * Class BuildProgressForm * @package ide\forms */ -class BuildProgressForm extends AbstractIdeForm +class BuildProgressForm extends AbstractIdeForm implements ProjectConsoleOutput { use SavableFormMixin; diff --git a/develnext/src/ide/forms/BuildProjectForm.php b/develnext/src/ide/forms/BuildProjectForm.php index 7d7d57ee..750d0840 100644 --- a/develnext/src/ide/forms/BuildProjectForm.php +++ b/develnext/src/ide/forms/BuildProjectForm.php @@ -1,135 +1,136 @@ -buildTypes = $buildTypes; - } - - protected function init() - { - $this->icon->image = Ide::get()->getImage('icons/box32.png')->image; - - $this->list->setCellFactory(function (UXListCell $cell, AbstractBuildType $item = null, $empty) { - if ($item) { - $titleName = new UXLabel($item->getName()); - $titleName->style = '-fx-font-weight: bold;'; - $titleName->padding = 0; - - $titleDescription = new UXLabel($item->getDescription()); - $titleDescription->style = '-fx-text-fill: gray;'; - - $box = new UXHBox([$titleName]); - $box->spacing = 0; - - if ($item->getConfigForm()) { - $settingsLink = new UXHyperlink('(настройки)'); - $settingsLink->padding = [0, 5]; - $settingsLink->on('action', function () use ($item) { - $item->showConfigDialog(); - }); - - $box->add($settingsLink); - } - - $title = new UXVBox([$box, $titleDescription]); - $title->spacing = 0; - - $list = []; - - if ($item->getIcon()) { - $list[] = Ide::get()->getImage($item->getIcon()); - } - - $list[] = $title; - - $line = new UXHBox($list); - - $line->spacing = 7; - $line->padding = 5; - - $cell->text = null; - $cell->graphic = $line; - } - }); - } - - /** - * @event show - */ - public function doShow() - { - Logger::info("Show build project dialog"); - - $this->list->items->addAll($this->buildTypes); - $this->list->selectedIndexes = [0]; - } - - /** - * @event cancelButton.action - */ - public function doCancelButtonClick() - { - $this->hide(); - } - - /** - * @param UXMouseEvent $e - * @event list.click - */ - public function doListClick(UXMouseEvent $e) - { - if ($e->clickCount > 1) { - $this->doBuildButtonClick(); - } - } - - /** - * @event buildButton.action - */ - public function doBuildButtonClick() - { - /** @var AbstractBuildType $buildType */ - $buildType = Items::first($this->list->selectedItems); - - if ($buildType) { - if ($buildType->fetchConfig()) { - $buildType->onExecute(Ide::get()->getOpenedProject()); - } - } else { - UXDialog::show('Данная функция находится в разработке.', 'INFORMATION'); - } - } +buildTypes = $buildTypes; + } + + protected function init() + { + $this->icon->image = Ide::get()->getImage('icons/box32.png')->image; + + $this->list->setCellFactory(function (UXListCell $cell, AbstractBuildType $item = null, $empty) { + if ($item) { + $titleName = new UXLabel($item->getName()); + $titleName->style = '-fx-font-weight: bold;'; + $titleName->padding = 0; + + $titleDescription = new UXLabel($item->getDescription()); + $titleDescription->style = '-fx-text-fill: gray;'; + + $box = new UXHBox([$titleName]); + $box->spacing = 0; + + if ($item->getConfigForm()) { + $settingsLink = new UXHyperlink('(настройки)'); + $settingsLink->padding = [0, 5]; + $settingsLink->on('action', function () use ($item) { + $item->showConfigDialog(); + }); + + $box->add($settingsLink); + } + + $title = new UXVBox([$box, $titleDescription]); + $title->spacing = 0; + + $list = []; + + if ($item->getIcon()) { + $list[] = Ide::get()->getImage($item->getIcon()); + } + + $list[] = $title; + + $line = new UXHBox($list); + + $line->spacing = 7; + $line->padding = 5; + + $cell->text = null; + $cell->graphic = $line; + } + }); + } + + /** + * @event show + */ + public function doShow() + { + Logger::info("Show build project dialog"); + + $this->list->items->addAll($this->buildTypes); + $this->list->selectedIndexes = [0]; + } + + /** + * @event cancelButton.action + */ + public function doCancelButtonClick() + { + $this->hide(); + } + + /** + * @param UXMouseEvent $e + * @event list.click + */ + public function doListClick(UXMouseEvent $e) + { + if ($e->clickCount > 1) { + $this->doBuildButtonClick(); + } + } + + /** + * @event buildButton.action + */ + public function doBuildButtonClick() + { + /** @var AbstractBuildType $buildType */ + $buildType = Items::first($this->list->selectedItems); + + if ($buildType) { + if ($buildType->fetchConfig()) { + $this->hide(); + $buildType->onExecute(Ide::get()->getOpenedProject()); + } + } else { + UXDialog::show('Данная функция находится в разработке.', 'INFORMATION'); + } + } } \ No newline at end of file diff --git a/develnext/src/ide/forms/MessageBoxForm.php b/develnext/src/ide/forms/MessageBoxForm.php index b4affad1..cdd9d4a0 100644 --- a/develnext/src/ide/forms/MessageBoxForm.php +++ b/develnext/src/ide/forms/MessageBoxForm.php @@ -1,145 +1,144 @@ -text = $text; - $this->buttons = $buttons; - } - - public function isChecked() - { - return $this->flag->selected; - } - - public function showDialogWithFlag() - { - UXApplication::runLater(function () { - $this->centerOnScreen(); - }); - return $this->_showDialog(); - } - - public function showDialog($x = null, $y = null) - { - $this->flag->free(); - UXApplication::runLater(function () { - $this->centerOnScreen(); - }); - return $this->_showDialog($x, $y); - } - - /** - * @return int - */ - public function getResultIndex() - { - return $this->indexResult; - } - - /** - * @event show - */ - public function doOpen() - { - $this->indexResult = -1; - $this->icon->image = Ide::get()->getImage('icons/question32.png')->image; - - $this->iconified = false; - $this->messageLabel->text = $this->text; - - $i = 0; - foreach ($this->buttons as $value => $button) - { - if ($button instanceof UXNode) { - $this->buttonBox->add($button); - continue; - } - - $ui = new UXButton($button); - $ui->maxHeight = 10000; - $ui->minWidth = 90; - $ui->height = 30; - $ui->paddingLeft = $ui->paddingRight = 15; - - $ui->on('action', function() use ($value, $i) { - $this->setResult($value); - $this->indexResult = $i; - $this->hide(); - }); - - if ($i++ == 0) { - $ui->style = '-fx-font-weight: bold'; - } - - $this->buttonBox->add($ui); - } - - UXApplication::runLater(function () { - $this->centerOnScreen(); - }); - } - - static function confirmDelete($what) - { - if (is_array($what)) { - $what = str::join($what, ", "); - } - - $dialog = new static("Вы уверены, что хотите удалить '$what'?", ['Да, удалить', 'Нет']); - - return $dialog->showDialog() && $dialog->getResultIndex() == 0; - } - - - static function confirmExit() - { - $dialog = new static("Вы уверены, что хотите выйти?", ['Да, выйти', 'Нет']); - return $dialog->showDialog() && $dialog->getResultIndex() == 0; - } +text = $text; + $this->buttons = $buttons; + } + + public function isChecked() + { + return $this->flag->selected; + } + + public function showDialogWithFlag() + { + UXApplication::runLater(function () { + $this->centerOnScreen(); + }); + return $this->_showDialog(); + } + + public function showDialog($x = null, $y = null) + { + $this->flag->free(); + UXApplication::runLater(function () { + $this->centerOnScreen(); + }); + return $this->_showDialog($x, $y); + } + + /** + * @return int + */ + public function getResultIndex() + { + return $this->indexResult; + } + + /** + * @event showing + */ + public function doOpen() + { + $this->indexResult = -1; + $this->icon->image = Ide::get()->getImage('icons/question32.png')->image; + + $this->iconified = false; + $this->messageLabel->text = $this->text; + + $i = 0; + foreach ($this->buttons as $value => $button) + { + if ($button instanceof UXNode) { + $this->buttonBox->add($button); + continue; + } + + $ui = new UXButton($button); + $ui->maxHeight = 10000; + $ui->minWidth = 90; + $ui->height = 30; + $ui->paddingLeft = $ui->paddingRight = 15; + + $ui->on('action', function() use ($value, $i) { + $this->setResult($value); + $this->indexResult = $i; + $this->hide(); + }); + + if ($i++ == 0) { + $ui->style = '-fx-font-weight: bold'; + } + + $this->buttonBox->add($ui); + } + + $this->layout->requestLayout(); + $this->centerOnScreen(); + } + + static function confirmDelete($what) + { + if (is_array($what)) { + $what = str::join($what, ", "); + } + + $dialog = new static("Вы уверены, что хотите удалить '$what'?", ['Да, удалить', 'Нет']); + + return $dialog->showDialog() && $dialog->getResultIndex() == 0; + } + + + static function confirmExit() + { + $dialog = new static("Вы уверены, что хотите выйти?", ['Да, выйти', 'Нет']); + return $dialog->showDialog() && $dialog->getResultIndex() == 0; + } } \ No newline at end of file diff --git a/develnext/src/ide/forms/OpenProjectForm.php b/develnext/src/ide/forms/OpenProjectForm.php index 21dc7528..6e276733 100644 --- a/develnext/src/ide/forms/OpenProjectForm.php +++ b/develnext/src/ide/forms/OpenProjectForm.php @@ -1,368 +1,369 @@ -tabPane->selectedIndex = 2; - break; - case 'embeddedLibrary': - $this->tabPane->selectedIndex = 1; - break; - } - } - } - - public function init() - { - parent::init(); - - $cellFactory = function (UXListCell $cell, IdeLibraryProjectResource $resource) { - $titleName = new UXLabel($resource->getName()); - $titleName->style = '-fx-font-weight: bold;'; - - $titleDescription = new UXLabel($resource->getDescription()); - $titleDescription->style = '-fx-text-fill: gray;'; - - if (!$titleDescription->text) { - $titleDescription->text = 'Проект без описания ...'; - } - - $actions = new UXHBox(); - $actions->spacing = 7; - - $openLink = new UXHyperlink('Открыть'); - $openLink->on('click', function () use ($resource, $cell) { - $cell->listView->selectedIndex = $cell->listView->items->indexOf($resource); - $this->doCreate(UXEvent::makeMock($cell->listView)); - }); - $actions->add($openLink); - - $deleteLink = new UXHyperlink('Удалить'); - $deleteLink->on('click', function () use ($resource, $cell) { - $cell->listView->selectedIndex = $cell->listView->items->indexOf($resource); - $this->doDelete(UXEvent::makeMock($cell->listView)); - }); - $actions->add($deleteLink); - - $title = new UXVBox([$titleName, $titleDescription, $actions]); - $title->spacing = 0; - - $line = new UXHBox([ico('archive32'), $title]); - $line->alignment = 'CENTER_LEFT'; - $line->spacing = 12; - $line->padding = 5; - - $cell->text = null; - $cell->graphic = $line; - $cell->style = ''; - }; - $this->embeddedLibraryList->setCellFactory($cellFactory); - $this->libraryList->setCellFactory($cellFactory); - - $this->projectListHelper = new FlowListViewDecorator($this->projectList->content); - $this->projectListHelper->setEmptyListText('Список проектов пуст.'); - $this->projectListHelper->setMultipleSelection(true); - $this->projectListHelper->on('remove', [$this, 'doRemove']); - $this->projectListHelper->on('beforeRemove', function ($nodes) { - $what = []; - foreach ($nodes as $node) { - $file = $node->data('file'); - - if ($file && $file->exists()) { - $what[] = $node->data('name'); - } - } - - if (!MessageBoxForm::confirmDelete($what)) { - return true; - } - - return false; - }); - - $this->icon->image = Ide::get()->getImage('icons/open32.png')->image; - $this->modality = 'APPLICATION_MODAL'; - $this->title = 'Открыть проект'; - } - - public function update() - { - $this->projectListHelper->clear(); - - $projectDirectory = File::of(Ide::get()->getUserConfigValue('projectDirectory')); - - $projects = []; - - foreach ($projectDirectory->findFiles() as $file) { - if ($file->isDirectory()) { - $project = Items::first($file->findFiles(function (File $directory, $name) { - return Str::endsWith($name, '.dnproject'); - })); - - if ($project) { - $projects[] = $project; - } - } - } - - Items::sort($projects, function (File $a, File $b) { - if ($a->lastModified() === $b->lastModified()) { - return 0; - } - - return $a->lastModified() > $b->lastModified() ? -1 : 1; - }); - - foreach ($projects as $project) { - /** @var File $project */ - $config = ProjectConfig::createForFile($project); - $template = $config->getTemplate(); - - $one = new ImageBox(72, 48); - $one->data('file', $project); - $one->data('name', FileUtils::stripExtension($project->getName())); - $one->setTitle(FileUtils::stripExtension($project->getName())); - $one->setImage(Ide::get()->getImage($template ? $template->getIcon32() : 'icons/question32.png')->image); - - $one->on('click', function (UXMouseEvent $e) { - $fix = $e; - UXApplication::runLater(function () use ($e) { - $this->doProjectListClick($e); - }); - }); - - $this->projectListHelper->add($one); - } - - $this->pathField->text = $projectDirectory; - } - - public function updateLibrary() - { - $this->libraryList->items->clear(); - $this->embeddedLibraryList->items->clear(); - - $libraryResources = Ide::get()->getLibrary()->getResources('projects'); - - foreach ($libraryResources as $resource) { - if (!$resource->isEmbedded()) { - $this->libraryList->items->add($resource); - } else { - $this->embeddedLibraryList->items->add($resource); - } - } - - $this->embeddedLibraryList->selectedIndex = 0; - $this->libraryList->selectedIndex = 0; - } - - /** - * @event show - */ - public function doShow() - { - $this->update(); - $this->updateLibrary(); - } - - /** - * @event openButton.click - */ - public function doOpenButtonClick() - { - if ($file = DialogSystem::getOpenProject()->execute()) { - $this->hide(); - - UXApplication::runLater(function () use ($file) { - if (Str::endsWith($file, ".zip")) { - ProjectSystem::import($file); - } else { - ProjectSystem::open($file); - } - }); - } - } - - /** - * @param $nodes - * @return bool - */ - public function doRemove(array $nodes) - { - foreach ($nodes as $node) { - $file = $node->data('file'); - - if ($file && $file->exists()) { - $directory = File::of($file)->getParent(); - - if (Ide::project() - && FileUtils::normalizeName(Ide::project()->getRootDir()) == FileUtils::normalizeName($directory)) { - ProjectSystem::closeWithWelcome(); - } - - if (!FileUtils::deleteDirectory($directory)) { - Notifications::error('Ошибка удаления', 'Папка проекта была не удалена полностью, возможно она занята другими программами.'); - $this->update(); - } - } - } - } - - /** - * @param UXMouseEvent $e - */ - public function doProjectListClick(UXMouseEvent $e) - { - if ($e->clickCount > 1) { - $node = $this->projectListHelper->getSelectionNode(); - $file = $node ? $node->data('file') : null; - - if ($file && $file->exists()) { - ProjectSystem::open($file); - $this->hide(); - } else { - UXDialog::show('Ошибка открытия проекта', 'ERROR'); - } - } - } - - /** - * @event pathButton.click - */ - public function doChoosePath() - { - $path = DialogSystem::getProjectsDirectory()->execute(); - - if ($path !== null) { - $this->pathField->text = $path; - - Ide::get()->setUserConfigValue('projectDirectory', $path); - $this->update(); - } - } - - /** - * @event embeddedLibraryList.click-2x - * @event libraryList.click-2x - * @param UXEvent $e - */ - public function doCreate(UXEvent $e) - { - /** @var UXListView $listView */ - $listView = $e->sender; - - /** @var IdeLibraryProjectResource $selected */ - $selected = $listView->selectedItem; - - if ($selected) { - $path = File::of($this->pathField->text); - - if (!$path->isDirectory()) { - if (!$path->mkdirs()) { - UXDialog::show('Невозможно создать папку проектов', 'ERROR'); - return; - } - } - - $name = FileUtils::stripExtension(File::of($selected->getPath())->getName()); - - ProjectSystem::import($selected->getPath(), "$path/$name", $name, [$this, 'hide']); - } - } - - public function doDelete(UXEvent $e) - { - /** @var UXListView $listView */ - $listView = $e->sender; - - /** @var IdeLibraryProjectResource $selected */ - $selected = $listView->selectedItem; - - if ($selected) { - if (MessageBoxForm::confirmDelete($selected->getName())) { - Ide::get()->getLibrary()->delete($selected); - $this->updateLibrary(); - $listView->selectedIndex = -1; - } - } - } - - public function selectLibraryResource(IdeLibraryResource $resource) - { - foreach ([$this->libraryList, $this->embeddedLibraryList] as $list) { - foreach ($list->items as $i => $it) { - if (FileUtils::equalNames($resource->getPath(), $it->getPath())) { - $list->selectedIndex = $i; - return; - } - } - } - } +tabPane->selectedIndex = 2; + break; + case 'embeddedLibrary': + $this->tabPane->selectedIndex = 1; + break; + } + } + } + + public function init() + { + parent::init(); + + $cellFactory = function (UXListCell $cell, IdeLibraryProjectResource $resource) { + $titleName = new UXLabel($resource->getName()); + $titleName->style = '-fx-font-weight: bold;'; + + $titleDescription = new UXLabel($resource->getDescription()); + $titleDescription->style = '-fx-text-fill: gray;'; + + if (!$titleDescription->text) { + $titleDescription->text = 'Проект без описания ...'; + } + + $actions = new UXHBox(); + $actions->spacing = 7; + + $openLink = new UXHyperlink('Открыть'); + $openLink->on('click', function () use ($resource, $cell) { + $cell->listView->selectedIndex = $cell->listView->items->indexOf($resource); + $this->doCreate(UXEvent::makeMock($cell->listView)); + }); + $actions->add($openLink); + + $deleteLink = new UXHyperlink('Удалить'); + $deleteLink->on('click', function () use ($resource, $cell) { + $cell->listView->selectedIndex = $cell->listView->items->indexOf($resource); + $this->doDelete(UXEvent::makeMock($cell->listView)); + }); + $actions->add($deleteLink); + + $title = new UXVBox([$titleName, $titleDescription, $actions]); + $title->spacing = 0; + + $line = new UXHBox([ico('archive32'), $title]); + $line->alignment = 'CENTER_LEFT'; + $line->spacing = 12; + $line->padding = 5; + + $cell->text = null; + $cell->graphic = $line; + $cell->style = ''; + }; + $this->embeddedLibraryList->setCellFactory($cellFactory); + $this->libraryList->setCellFactory($cellFactory); + + $this->projectListHelper = new FlowListViewDecorator($this->projectList->content); + $this->projectListHelper->setEmptyListText('Список проектов пуст.'); + $this->projectListHelper->setMultipleSelection(true); + $this->projectListHelper->on('remove', [$this, 'doRemove']); + $this->projectListHelper->on('beforeRemove', function ($nodes) { + $what = []; + foreach ($nodes as $node) { + $file = $node->data('file'); + + if ($file && $file->exists()) { + $what[] = $node->data('name'); + } + } + + if (!MessageBoxForm::confirmDelete($what)) { + return true; + } + + return false; + }); + + $this->icon->image = Ide::get()->getImage('icons/open32.png')->image; + $this->modality = 'APPLICATION_MODAL'; + $this->title = 'Открыть проект'; + } + + public function update() + { + $this->projectListHelper->clear(); + + $projectDirectory = File::of(Ide::get()->getUserConfigValue('projectDirectory')); + + $projects = []; + + foreach ($projectDirectory->findFiles() as $file) { + if ($file->isDirectory()) { + $project = Items::first($file->findFiles(function (File $directory, $name) { + return Str::endsWith($name, '.dnproject'); + })); + + if ($project) { + $projects[] = $project; + } + } + } + + Items::sort($projects, function (File $a, File $b) { + if ($a->lastModified() === $b->lastModified()) { + return 0; + } + + return $a->lastModified() > $b->lastModified() ? -1 : 1; + }); + + foreach ($projects as $project) { + /** @var File $project */ + $config = ProjectConfig::createForFile($project); + $template = $config->getTemplate(); + + $one = new ImageBox(72, 48); + $one->data('file', $project); + $one->data('name', FileUtils::stripExtension($project->getName())); + $one->setTitle(FileUtils::stripExtension($project->getName())); + $one->setImage(Ide::get()->getImage($template ? $template->getIcon32() : 'icons/question32.png')->image); + + $one->on('click', function (UXMouseEvent $e) { + $fix = $e; + UXApplication::runLater(function () use ($e) { + $this->doProjectListClick($e); + }); + }); + + $this->projectListHelper->add($one); + } + + $this->pathField->text = $projectDirectory; + } + + public function updateLibrary() + { + $this->libraryList->items->clear(); + $this->embeddedLibraryList->items->clear(); + + $libraryResources = Ide::get()->getLibrary()->getResources('projects'); + + foreach ($libraryResources as $resource) { + if (!$resource->isEmbedded()) { + $this->libraryList->items->add($resource); + } else { + $this->embeddedLibraryList->items->add($resource); + } + } + + $this->embeddedLibraryList->selectedIndex = 0; + $this->libraryList->selectedIndex = 0; + } + + /** + * @event show + */ + public function doShow() + { + $this->update(); + $this->updateLibrary(); + } + + /** + * @event openButton.click + */ + public function doOpenButtonClick() + { + if ($file = DialogSystem::getOpenProject()->execute()) { + $this->hide(); + + UXApplication::runLater(function () use ($file) { + if (Str::endsWith($file, ".zip")) { + ProjectSystem::import($file); + } else { + ProjectSystem::open($file); + } + }); + } + } + + /** + * @param $nodes + * @return bool + */ + public function doRemove(array $nodes) + { + foreach ($nodes as $node) { + $file = $node->data('file'); + + if ($file && $file->exists()) { + $directory = File::of($file)->getParent(); + + if (Ide::project() + && FileUtils::normalizeName(Ide::project()->getRootDir()) == FileUtils::normalizeName($directory)) { + ProjectSystem::closeWithWelcome(); + } + + if (!FileUtils::deleteDirectory($directory)) { + Notifications::error('Ошибка удаления', 'Папка проекта была не удалена полностью, возможно она занята другими программами.'); + $this->update(); + } + } + } + } + + /** + * @param UXMouseEvent $e + */ + public function doProjectListClick(UXMouseEvent $e) + { + if ($e->clickCount > 1) { + $node = $this->projectListHelper->getSelectionNode(); + $file = $node ? $node->data('file') : null; + + if ($file && $file->exists()) { + $this->hide(); + ProjectSystem::open($file); + } else { + UXDialog::show('Ошибка открытия проекта', 'ERROR'); + } + } + } + + /** + * @event pathButton.click + */ + public function doChoosePath() + { + $path = DialogSystem::getProjectsDirectory()->execute(); + + if ($path !== null) { + $this->pathField->text = $path; + + Ide::get()->setUserConfigValue('projectDirectory', $path); + $this->update(); + } + } + + /** + * @event embeddedLibraryList.click-2x + * @event libraryList.click-2x + * @param UXEvent $e + */ + public function doCreate(UXEvent $e) + { + /** @var UXListView $listView */ + $listView = $e->sender; + + /** @var IdeLibraryProjectResource $selected */ + $selected = $listView->selectedItem; + + if ($selected) { + $path = File::of($this->pathField->text); + + if (!$path->isDirectory()) { + if (!$path->mkdirs()) { + UXDialog::show('Невозможно создать папку проектов', 'ERROR'); + return; + } + } + + $name = FileUtils::stripExtension(File::of($selected->getPath())->getName()); + + $this->hide(); + ProjectSystem::import($selected->getPath(), "$path/$name", $name, [$this, 'hide']); + } + } + + public function doDelete(UXEvent $e) + { + /** @var UXListView $listView */ + $listView = $e->sender; + + /** @var IdeLibraryProjectResource $selected */ + $selected = $listView->selectedItem; + + if ($selected) { + if (MessageBoxForm::confirmDelete($selected->getName())) { + Ide::get()->getLibrary()->delete($selected); + $this->updateLibrary(); + $listView->selectedIndex = -1; + } + } + } + + public function selectLibraryResource(IdeLibraryResource $resource) + { + foreach ([$this->libraryList, $this->embeddedLibraryList] as $list) { + foreach ($list->items as $i => $it) { + if (FileUtils::equalNames($resource->getPath(), $it->getPath())) { + $list->selectedIndex = $i; + return; + } + } + } + } } \ No newline at end of file diff --git a/develnext/src/ide/project/AbstractProjectBehaviour.php b/develnext/src/ide/project/AbstractProjectBehaviour.php index 7856fb92..d68bcbc1 100644 --- a/develnext/src/ide/project/AbstractProjectBehaviour.php +++ b/develnext/src/ide/project/AbstractProjectBehaviour.php @@ -12,7 +12,13 @@ */ abstract class AbstractProjectBehaviour { + const PRIORITY_SYSTEM = 1; + const PRIORITY_CORE = 100; + const PRIORITY_LIBRARY = 1000; + const PRIORITY_COMPONENT = 10000; + use VendorContainer; + use ProjectIdeConfigurable; /** * @var Project @@ -24,6 +30,12 @@ abstract class AbstractProjectBehaviour */ abstract public function inject(); + /** + * see PRIORITY_* constants + * @return int + */ + abstract public function getPriority(); + /** * @param DomElement $domBehavior * @param DomDocument $document diff --git a/develnext/src/ide/project/ProjectConfig.php b/develnext/src/ide/project/ProjectConfig.php index 560e479b..5895f558 100644 --- a/develnext/src/ide/project/ProjectConfig.php +++ b/develnext/src/ide/project/ProjectConfig.php @@ -10,6 +10,7 @@ use php\io\IOException; use php\io\Stream; use php\lang\System; +use php\lib\arr; use php\lib\Str; use php\time\Time; use php\util\Scanner; @@ -380,16 +381,32 @@ public function createBehaviours(Project $project) $behaviour = new $class(); if ($behaviour instanceof AbstractProjectBehaviour) { - $behaviour = $project->register($behaviour); - $behaviour->unserialize($domBehaviour); - $behaviours[get_class($behaviour)] = $behaviour; } } else { - throw new InvalidProjectFormatException("Class behaviour '$class' is not exists."); + Logger::error("Unable add project behaviour, class '$class' is not found."); } } + $behaviours = arr::sort($behaviours, function (AbstractProjectBehaviour $a, AbstractProjectBehaviour $b) { + if ($a->getPriority() > $b->getPriority()) { + return 1; + } else { + if ($a->getPriority() < $b->getPriority()) { + return -1; + } + + return 0; + } + }, true); + + foreach ($behaviours as $class => $behaviour) { + $behaviour = $project->register($behaviour); + $behaviour->unserialize($domBehaviour); + + $behaviours[$class] = $behaviour; + } + return $behaviours; } diff --git a/develnext/src/ide/project/ProjectConsoleOutput.php b/develnext/src/ide/project/ProjectConsoleOutput.php new file mode 100644 index 00000000..7edf5a23 --- /dev/null +++ b/develnext/src/ide/project/ProjectConsoleOutput.php @@ -0,0 +1,8 @@ +getIdeConfig()) { + return $config->get($key, $def); + } + + return null; + } + + /** + * @param $key + * @param $value + * @return null + */ + protected function setIdeConfigValue($key, $value) + { + if ($config = $this->getIdeConfig()) { + $config->set($key, $value); + } + } + + /** + * @return \php\util\Configuration + */ + protected function getIdeConfig() + { + if (Ide::project()) { + $name = str::replace(get_class($this), "\\", "/") . ".conf"; + + return Ide::project()->getIdeConfig($name); + } else { + return null; + } + } + + protected function saveIdeConfig() + { + if (Ide::project()) { + $file = get_class($this); + $name = str::replace(get_class($this), "\\", "/") . ".conf"; + + Ide::project()->saveIdeConfig($name); + } + } +} \ No newline at end of file diff --git a/develnext/src/ide/project/behaviours/BundleProjectBehaviour.php b/develnext/src/ide/project/behaviours/BundleProjectBehaviour.php index b316f538..012584ab 100644 --- a/develnext/src/ide/project/behaviours/BundleProjectBehaviour.php +++ b/develnext/src/ide/project/behaviours/BundleProjectBehaviour.php @@ -6,7 +6,12 @@ use ide\editors\ProjectEditor; use ide\project\AbstractProjectBehaviour; use ide\project\Project; +use ide\utils\FileUtils; +use ide\utils\PhpParser; use php\gui\layout\UXHBox; +use php\gui\layout\UXVBox; +use php\gui\UXButton; +use php\gui\UXCheckbox; use php\gui\UXLabel; use php\gui\UXNode; use php\lib\fs; @@ -26,6 +31,11 @@ class BundleProjectBehaviour extends AbstractProjectBehaviour */ protected $uiSettings; + /** + * @var UXHBox + */ + protected $uiPackages; + /** * @var AbstractBundle[] */ @@ -36,6 +46,19 @@ class BundleProjectBehaviour extends AbstractProjectBehaviour */ protected $bundleConfigs = []; + /** + * @var UXCheckbox + */ + protected $uiUseImportCheckbox; + + /** + * @return int + */ + public function getPriority() + { + return self::PRIORITY_SYSTEM; + } + /** * ... */ @@ -61,6 +84,10 @@ public function doSave() $bundle->onSave($this->project, $config); } } + + if ($this->uiSettings) { + $this->setIdeConfigValue(self::CONFIG_BUNDLE_KEY_USE_IMPORTS, $this->uiUseImportCheckbox->selected); + } } public function doLoad() @@ -87,8 +114,53 @@ public function doLoad() } } + protected function doPreCompileUseImports($env, callable $log = null) + { + if ($this->getIdeConfigValue(self::CONFIG_BUNDLE_KEY_USE_IMPORTS, true)) { + $withSourceMap = Project::ENV_DEV == $env; + $imports = []; + + $allBundles = $this->fetchAllBundles($env); + + foreach ($allBundles as $bundle) { + foreach ($bundle->getUseImports() as $useImport) { + $imports[$useImport] = [$useImport]; + } + } + + if ($imports) { + FileUtils::scan($this->project->getFile('src/app'), function ($filename) use ($imports, $log, $withSourceMap) { + if (str::endsWith($filename, '.php')) { + $phpParser = PhpParser::ofFile($filename, $withSourceMap); + + $phpParser->addUseImports($imports); + + if ($log) { + $filename = fs::normalize($filename); + $file = $this->project->getAbsoluteFile($filename); + + if (!$file->exists()) { + return; + } + + $log(":import use '{$file->getRelativePath()}'"); + } + + $phpParser->saveContent($filename, $withSourceMap); + } + }); + } + } + } + public function doPreCompile($env, callable $log = null) { + FileUtils::scan($this->project->getFile('src/'), function ($filename) { + if (str::endsWith($filename, '.php.source')) { + FileUtils::copyFile($filename, FileUtils::stripExtension($filename)); // rewrite from origin. + } + }); + $gradle = GradleProjectBehaviour::get(); $allBundles = $this->fetchAllBundles($env); @@ -112,21 +184,7 @@ public function doPreCompile($env, callable $log = null) } } - $php = PhpProjectBehaviour::get(); - - if ($php) { - $php->clearGlobalUseImports(); - - foreach ($allBundles as $bundle) { - $config = $this->getBundleConfig($bundle); - - //if (!$config || $config->get(self::CONFIG_BUNDLE_KEY_USE_IMPORTS, true)) { - foreach ($bundle->getUseImports() as $useImport) { - $php->addGlobalUseImport($useImport); - } - // } - } - } + $this->doPreCompileUseImports($env, $log); } /** @@ -147,10 +205,10 @@ public function fetchAllBundles($env) } }; - $groups = [(array) $this->bundles[$env]]; + $groups = [(array)$this->bundles[$env]]; if ($env != Project::ENV_ALL) { - $groups[] = (array) $this->bundles[Project::ENV_ALL]; + $groups[] = (array)$this->bundles[Project::ENV_ALL]; } /** @var AbstractBundle $bundle */ @@ -233,13 +291,45 @@ public function getBundleConfig(AbstractBundle $bundle) public function doUpdateSettings(ProjectEditor $editor = null) { if ($this->uiSettings) { + $this->uiPackages->children->clear(); + + foreach ($this->bundles as $env => $group) { + /** @var AbstractBundle $bundle */ + foreach ($group as $bundle) { + $uiItem = new UXButton($bundle->getName() . " [$env]"); + $uiItem->tooltipText = $bundle->getDescription(); + + $this->uiPackages->add($uiItem); + } + } + + $addButton = new UXButton(); + $addButton->graphic = ico('plus16'); + $addButton->on('action', function () { + alert('В разработке ...'); + }); + $this->uiPackages->add($addButton); + $this->uiUseImportCheckbox->selected = $this->getIdeConfigValue(self::CONFIG_BUNDLE_KEY_USE_IMPORTS, true); } } public function doMakeSettings(ProjectEditor $editor) { - $ui = new UXHBox([new UXLabel('Пакеты: ')]); + $title = new UXLabel('Пакеты:'); + $title->font = $title->font->withBold(); + + $packages = new UXHBox(); + $packages->spacing = 5; + $this->uiPackages = $packages; + + $this->uiUseImportCheckbox = $useImportCheckbox = new UXCheckbox("Добавлять use импорты классов"); + $useImportCheckbox->tooltipText = 'Добавлять во все исходники подключение классов через use из всех пакетов'; + + $ui = new UXVBox([$title, $packages, $useImportCheckbox]); + $ui->spacing = 5; + + $this->uiSettings = $ui; $editor->addSettingsPane($ui); } diff --git a/develnext/src/ide/project/behaviours/GradleProjectBehaviour.php b/develnext/src/ide/project/behaviours/GradleProjectBehaviour.php index cd3c8b3e..2c471d3d 100644 --- a/develnext/src/ide/project/behaviours/GradleProjectBehaviour.php +++ b/develnext/src/ide/project/behaviours/GradleProjectBehaviour.php @@ -81,4 +81,13 @@ public function getConfig() { return $this->config; } + + /** + * see PRIORITY_* constants + * @return int + */ + public function getPriority() + { + return self::PRIORITY_COMPONENT; + } } \ No newline at end of file diff --git a/develnext/src/ide/project/behaviours/GuiFrameworkProjectBehaviour.php b/develnext/src/ide/project/behaviours/GuiFrameworkProjectBehaviour.php index c649160c..7306db7b 100644 --- a/develnext/src/ide/project/behaviours/GuiFrameworkProjectBehaviour.php +++ b/develnext/src/ide/project/behaviours/GuiFrameworkProjectBehaviour.php @@ -43,6 +43,7 @@ use ide\utils\FileUtils; use ide\utils\Json; use php\gui\layout\UXHBox; +use php\gui\layout\UXVBox; use php\gui\UXLabel; use php\io\File; use php\io\IOException; @@ -91,6 +92,14 @@ class GuiFrameworkProjectBehaviour extends AbstractProjectBehaviour */ protected $applicationConfig; + /** + * @return int + */ + public function getPriority() + { + return self::PRIORITY_LIBRARY; + } + /** * ... */ @@ -102,6 +111,7 @@ public function inject() $this->project->on('create', [$this, 'doCreate']); $this->project->on('open', [$this, 'doOpen']); $this->project->on('updateTree', [$this, 'doUpdateTree']); + $this->project->on('preCompile', [$this, 'doPreCompile']); $this->project->on('compile', [$this, 'doCompile']); $this->project->on('export', [$this, 'doExport']); $this->project->on('reindex', [$this, 'doReindex']); @@ -116,8 +126,9 @@ public function inject() $buildProjectCommand->register(new SetupWindowsApplicationBuildType()); $buildProjectCommand->register(new OneJarBuildType()); - Ide::get()->registerCommand($buildProjectCommand); Ide::get()->registerCommand(new ExecuteProjectCommand()); + Ide::get()->registerCommand($buildProjectCommand); + Ide::get()->registerCommand(new CreateFormProjectCommand()); Ide::get()->registerCommand(new CreateScriptModuleProjectCommand()); //Ide::get()->registerCommand(new CreateFactoryProjectCommand()); @@ -208,7 +219,13 @@ public function doMakeSettings(ProjectEditor $editor) $this->settingsMainFormCombobox = $formListEditor; - $editor->addSettingsPane($ui); + $title = new UXLabel('Интерфейс:'); + $title->font = $title->font->withBold(); + + $wrap = new UXVBox([$title, $ui]); + $wrap->spacing = 5; + + $editor->addSettingsPane($wrap); } public function doReindex(ProjectIndexer $indexer) @@ -228,20 +245,22 @@ public function doExport(ProjectExporter $exporter) $exporter->removeFile($this->project->getFile('src/.debug')); } - public function doCompile($environment, callable $log = null) + public function doPreCompile($env, callable $log = null) { - $this->updateScriptManager(); - - if ($log) { - $log(':dn-compile-actions'); - } + $withSourceMap = $env == Project::ENV_DEV; $this->actionManager->compile($this->project->getFile('src/'), function ($filename) use ($log) { $name = $this->project->getAbsoluteFile($filename)->getRelativePath(); + if ($log) { - $log(':compile "' . $name . '"'); + $log(':apply actions "' . $name . '"'); } - }); + }, $withSourceMap); + } + + public function doCompile($environment, callable $log = null) + { + $this->updateScriptManager(); $modules = $this->scriptComponentManager->getModules(); $values = []; diff --git a/develnext/src/ide/project/behaviours/PhpProjectBehaviour.php b/develnext/src/ide/project/behaviours/PhpProjectBehaviour.php index 8d93df64..2fab85f2 100644 --- a/develnext/src/ide/project/behaviours/PhpProjectBehaviour.php +++ b/develnext/src/ide/project/behaviours/PhpProjectBehaviour.php @@ -1,11 +1,18 @@ project->on('open', [$this, 'doOpen']); + $this->project->on('save', [$this, 'doSave']); + $this->project->on('preCompile', [$this, 'doPreCompile']); $this->project->on('compile', [$this, 'doCompile']); + + $this->project->on('makeSettings', [$this, 'doMakeSettings']); + $this->project->on('updateSettings', [$this, 'doUpdateSettings']); } public function doOpen() { } - public function doCompile($env, callable $log = null) + public function doSave() { - if ($this->globalUseImports) { - $imports = []; + if ($this->uiSettings) { + $this->setIdeConfigValue(self::OPT_COMPILE_BYTE_CODE, $this->uiByteCodeCheckbox->selected); + } + } - foreach ($this->globalUseImports as $import) { - $imports[] = [$import]; + public function doPreCompile() + { + FileUtils::scan($this->project->getFile(self::SOURCES_DIRECTORY), function ($filename) { + if (str::endsWith($filename, '.php.sourcemap')) { + fs::delete($filename); + } + + if (fs::ext($filename) == '.phb') { + fs::delete($filename); } + }); + } + + public function doCompile($env, callable $log = null) + { + $useByteCode = Project::ENV_PROD == $env; + if ($useByteCode && $this->getIdeConfigValue(self::OPT_COMPILE_BYTE_CODE)) { $scope = new Environment(null, Environment::HOT_RELOAD); $jarLibraries = $this->externalJarLibraries; @@ -65,13 +113,16 @@ public function doCompile($env, callable $log = null) spl_autoload_register(function ($name) use ($jarLibraries, $sourceDir) { foreach ($jarLibraries as $file) { + if (!fs::exists($file)) { + echo "SKIP $file, is not exists.\n"; + continue; + } + try { $name = str::replace($name, '\\', '/'); $url = new URL("jar:file:/$file!/$name.php"); - echo "Search in class in ", $file, "\n"; - $conn = $url->openConnection(); $stream = $conn->getInputStream(); @@ -80,6 +131,8 @@ public function doCompile($env, callable $log = null) $stream->close(); + echo "Find class '$name' in ", $file, "\n"; + $compiled = new File($sourceDir, $name . ".phb"); if ($compiled->getParentFile() && !$compiled->getParentFile()->isDirectory()) { @@ -96,46 +149,52 @@ public function doCompile($env, callable $log = null) }); }); - FileUtils::scan($this->project->getFile(self::SOURCES_DIRECTORY), function ($filename) use ($imports, $log, $scope) { + FileUtils::scan($this->project->getFile(self::SOURCES_DIRECTORY), function ($filename) use ($log, $scope, $useByteCode) { if (str::endsWith($filename, '.php')) { - /*$phpParser = new PhpParser(FileUtils::get($filename)); - - $phpParser->addUseImports($imports); + $filename = fs::normalize($filename); if ($log) { - $filename = fs::normalize($filename); - $file = $this->project->getAbsoluteFile($filename); - - if (!$file->exists()) { - return; - } - - $log(":import use '{$file->getRelativePath()}'"); + $log(":compile $filename"); } - FileUtils::put($filename, $phpParser->getContent()); */ - - /*$scope->execute(function () use ($filename) { + $scope->execute(function () use ($filename) { $module = new Module($filename, false, true); $module->dump(fs::parent($filename) . '/' . fs::nameNoExt($filename) . '.phb', true); - }); */ + }); } }); } } - public function clearGlobalUseImports() + public function addExternalJarLibrary($file) { - $this->globalUseImports = []; + $this->externalJarLibraries[FileUtils::hashName($file)] = $file; } - public function addGlobalUseImport($class) + + public function doUpdateSettings(ProjectEditor $editor = null) { - $this->globalUseImports[$class] = $class; + if ($this->uiSettings) { + $this->uiByteCodeCheckbox->selected = $this->getIdeConfigValue(self::OPT_COMPILE_BYTE_CODE, false); + } } - public function addExternalJarLibrary($file) + public function doMakeSettings(ProjectEditor $editor) { - $this->externalJarLibraries[FileUtils::hashName($file)] = $file; + $title = new UXLabel('Исходный код:'); + $title->font = $title->font->withBold(); + + $opts = new UXHBox(); + $opts->spacing = 5; + + $this->uiByteCodeCheckbox = $byteCodeCheckbox = new UXCheckbox('Компилировать в байткод'); + $byteCodeCheckbox->tooltipText = 'Компиляция будет происходить только во время итоговой сборки проекта.'; + $opts->add($byteCodeCheckbox); + + $ui = new UXVBox([$title, $opts]); + $ui->spacing = 5; + $this->uiSettings = $ui; + + $editor->addSettingsPane($ui); } } \ No newline at end of file diff --git a/develnext/src/ide/project/templates/DefaultGuiProjectTemplate.php b/develnext/src/ide/project/templates/DefaultGuiProjectTemplate.php index a57da3b5..464c1218 100644 --- a/develnext/src/ide/project/templates/DefaultGuiProjectTemplate.php +++ b/develnext/src/ide/project/templates/DefaultGuiProjectTemplate.php @@ -35,16 +35,16 @@ public function getIcon32() public function recoveryProject(Project $project) { - if (!$project->hasBehaviour(GuiFrameworkProjectBehaviour::class)) { - $project->register(new GuiFrameworkProjectBehaviour()); + if (!$project->hasBehaviour(BundleProjectBehaviour::class)) { + $project->register(new BundleProjectBehaviour()); } if (!$project->hasBehaviour(PhpProjectBehaviour::class)) { $project->register(new PhpProjectBehaviour()); } - if (!$project->hasBehaviour(BundleProjectBehaviour::class)) { - $project->register(new BundleProjectBehaviour()); + if (!$project->hasBehaviour(GuiFrameworkProjectBehaviour::class)) { + $project->register(new GuiFrameworkProjectBehaviour()); } } @@ -55,9 +55,9 @@ public function recoveryProject(Project $project) */ public function makeProject(Project $project) { - $project->register(new GuiFrameworkProjectBehaviour()); - $project->register(new PhpProjectBehaviour()); $project->register(new BundleProjectBehaviour()); + $project->register(new PhpProjectBehaviour()); + $project->register(new GuiFrameworkProjectBehaviour()); $project->setIgnoreRules([ '*.log', '*.tmp' diff --git a/develnext/src/ide/systems/ProjectSystem.php b/develnext/src/ide/systems/ProjectSystem.php index 8c3c926b..8f9701ce 100644 --- a/develnext/src/ide/systems/ProjectSystem.php +++ b/develnext/src/ide/systems/ProjectSystem.php @@ -8,6 +8,7 @@ use ide\project\AbstractProjectTemplate; use ide\project\InvalidProjectFormatException; use ide\project\Project; +use ide\project\ProjectConsoleOutput; use ide\project\ProjectImporter; use ide\ui\Notifications; use ide\utils\FileUtils; @@ -16,6 +17,7 @@ use php\gui\UXDirectoryChooser; use php\io\File; use php\io\IOException; +use php\lang\Thread; use php\lib\fs; use php\lib\Items; use php\lib\Str; @@ -35,6 +37,47 @@ protected static function clear() Ide::get()->unregisterCommands(); } + /** + * Compile full project. + * + * @param string $env + * @param ProjectConsoleOutput $consoleOutput + * @param string $hintCommand + * @param callable $callback + */ + static function compileAll($env, ProjectConsoleOutput $consoleOutput, $hintCommand, callable $callback) + { + $project = Ide::project(); + + if (!$project) { + return; + } + + $th = new Thread(function () use ($project, $consoleOutput, $callback, $env, $hintCommand) { + $project->preCompile($env, function ($log) use ($consoleOutput) { + uiLater(function () use ($consoleOutput, $log) { + $consoleOutput->addConsoleLine($log, 'gray'); + }); + }); + + $project->compile($env, function ($log) use ($consoleOutput) { + uiLater(function () use ($consoleOutput, $log) { + $consoleOutput->addConsoleLine($log, 'blue'); + }); + }); + + uiLater(function () use ($consoleOutput, $project, $hintCommand) { + $consoleOutput->addConsoleLine('> ' . $hintCommand, 'green'); + $consoleOutput->addConsoleLine(' --> ' . $project->getRootDir() . ' ..', 'gray'); + }); + + uiLater($callback); + }); + + $th->start(); + } + + static public function checkDirectory($path) { Logger::info("Check directory: $path"); @@ -87,6 +130,7 @@ static function import($file, $projectDir = null, $newName = null, callable $aft if (!($projectDir = self::checkDirectory($projectDir))) { Ide::get()->getMainForm()->hidePreloader(); + ProjectSystem::closeWithWelcome(); return; } diff --git a/develnext/src/ide/utils/PhpParser.php b/develnext/src/ide/utils/PhpParser.php index b085145d..b5635eb1 100644 --- a/develnext/src/ide/utils/PhpParser.php +++ b/develnext/src/ide/utils/PhpParser.php @@ -1,8 +1,10 @@ content = $content; - $this->sourceMap = new SourceMap(null); + $this->setContent($content); + + if ($sourceMapFile) { + $this->applySourceMapFile($sourceMapFile); + } + } + + /** + * @param $file + * @param bool $withSourceMap + * @return PhpParser + */ + static function ofFile($file, $withSourceMap = false) + { + return new PhpParser(FileUtils::get($file), $withSourceMap ? $file . '.sourcemap' : null); } /** @@ -42,12 +72,67 @@ public function getContent() return $this->content; } + /** + * @param string $sourceMapFile json source map + */ + public function applySourceMapFile($sourceMapFile) + { + $this->sourceMapFile = $sourceMapFile; + + if (fs::isFile($sourceMapFile)) { + $map = (array) Json::fromFile($sourceMapFile); + + if ($map) { + $this->sourceMap = new SourceMap(null); + + foreach ($map as $cLine => $sLine) { + $this->sourceMap->addLine($sLine, $cLine); + } + } + } + } + /** * @return SourceMap */ public function getSourceMap() { - return $this->sourceMap; + $sourceMap = new SourceMap(null); + + if ($this->sourceMap) { + foreach ($this->sourceMap->toArray() as $cLine => $sLine) { + $sourceMap->addLine($sLine, $cLine); + } + } + + $sourceMap->insertLines($this->sourceMapInserts, $this->contentLineCount); + + return $sourceMap; + } + + /** + * @param string $toFile + * @param bool $saveSourceMap + */ + public function saveContent($toFile, $saveSourceMap = false) + { + FileUtils::put($toFile, $this->getContent()); + + if ($saveSourceMap) { + $this->saveSourceMap($toFile . '.sourcemap'); + } + } + + /** + * @param $file + */ + public function saveSourceMap($file = null) + { + if (!$file) { + $file = $this->sourceMapFile; + } + + Json::toFile($file, $this->getSourceMap()->toArray()); } /** @@ -56,6 +141,8 @@ public function getSourceMap() public function setContent($content) { $this->content = $content; + $this->sourceMapInserts = []; + $this->contentLineCount = StrUtils::lineCount($content); } /** @@ -219,24 +306,13 @@ public function insertAfterLine($lineNumber, $text) $i = 0; $inserted = false; - $insertedLines = new SharedValue(0); while ($scanner->hasNextLine()) { $line = $scanner->nextLine(); $content .= $line . "\n"; - if ($insertedLines->get()) { - $originI = $this->sourceMap->getSourceLine($i + 1); - - if ($originI == -1) { - $this->sourceMap->addLine($i + 1, $i + $insertedLines->get() + 1); - } else { - $this->sourceMap->addLine($originI, $originI + $insertedLines->get()); - } - } - if ($i == $lineNumber) { - $insertedLines->set(StrUtils::lineCount($text, true)); + $this->sourceMapInserts[] = [$lineNumber + 1, StrUtils::lineCount($text, true)]; $content .= $text . "\n"; $inserted = true; diff --git a/develnext/src/ide/utils/StrUtils.php b/develnext/src/ide/utils/StrUtils.php index 19bbee55..e44deaff 100644 --- a/develnext/src/ide/utils/StrUtils.php +++ b/develnext/src/ide/utils/StrUtils.php @@ -2,6 +2,7 @@ namespace ide\utils; +use php\lib\str; use php\util\Scanner; class StrUtils @@ -18,6 +19,10 @@ static function lineCount($text, $emptyIsLine = false) $result++; } + if (str::endsWith($text, "\n") || str::endsWith($text, "\r")) { + $result += 1; + } + if ($emptyIsLine && $result == 0 && !$text) { $result = 1; } diff --git a/develnext/windowsSetup/innopatchsetup.iss b/develnext/windowsSetup/innopatchsetup.iss new file mode 100644 index 00000000..85edd4d0 --- /dev/null +++ b/develnext/windowsSetup/innopatchsetup.iss @@ -0,0 +1,47 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "DevelNext Patch" +#define MyAppVersion "Patch-A" +#define MyAppPublisher "develnext.org" +#define MyAppURL "http://develnext.org" +#define MyAppExeName "DevelNext.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{CA74A9B0-AFDA-4D34-8CA1-5F2122F71ABF} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName=DevelNext IDE +OutputDir=../build/distributions/ +OutputBaseFilename=DevelNext.WindowsPatch +Compression=lzma +SolidCompression=yes +WizardImageFile=wizardPatchImage.bmp + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl" + +[Files] +Source: "../build/install/develnext/DevelNext.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "../build/install/develnext/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + +[Registry] +Root: HKCR; Subkey: "develnext"; ValueType: "string"; ValueData: "URL:DevelNext Protocol"; Flags: uninsdeletekey +Root: HKCR; Subkey: "develnext"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: "" +Root: HKCR; Subkey: "develnext\DefaultIcon"; ValueType: "string"; ValueData: "{app}\DevelNext.exe,0" +Root: HKCR; Subkey: "develnext\shell\open\command"; ValueType: "string"; ValueData: """{app}\DevelNext.exe"" ""%1""" + diff --git a/develnext/windowsSetup/wizardPatchImage.bmp b/develnext/windowsSetup/wizardPatchImage.bmp new file mode 100644 index 00000000..29b863fa Binary files /dev/null and b/develnext/windowsSetup/wizardPatchImage.bmp differ diff --git a/jphp-gui-ext/src/main/java/org/develnext/jphp/ext/javafx/classes/text/UXFont.java b/jphp-gui-ext/src/main/java/org/develnext/jphp/ext/javafx/classes/text/UXFont.java index 67eec412..e08e2b26 100644 --- a/jphp-gui-ext/src/main/java/org/develnext/jphp/ext/javafx/classes/text/UXFont.java +++ b/jphp-gui-ext/src/main/java/org/develnext/jphp/ext/javafx/classes/text/UXFont.java @@ -1,103 +1,155 @@ -package org.develnext.jphp.ext.javafx.classes.text; - -import javafx.scene.text.Font; -import javafx.scene.text.FontPosture; -import javafx.scene.text.FontWeight; -import org.develnext.jphp.ext.javafx.JavaFXExtension; -import php.runtime.annotation.Reflection; -import php.runtime.annotation.Reflection.Getter; -import php.runtime.annotation.Reflection.Property; -import php.runtime.annotation.Reflection.Signature; -import php.runtime.env.Environment; -import php.runtime.lang.BaseWrapper; -import php.runtime.reflection.ClassEntity; - -import java.io.InputStream; -import java.util.List; - -@Reflection.Name(JavaFXExtension.NS + "text\\UXFont") -public class UXFont extends BaseWrapper { - interface WrappedInterface { - @Property String name(); - @Property String family(); - @Property String size(); - @Property String style(); - } - - public UXFont(Environment env, Font wrappedObject) { - super(env, wrappedObject); - } - - public UXFont(Environment env, ClassEntity clazz) { - super(env, clazz); - } - - @Signature - public void __construct(double size) { - __wrappedObject = new Font(size); - } - - @Signature - public void __construct(double size, String name) { - __wrappedObject = new Font(name, size); - } - - @Signature - public static List getFamilies() { - return Font.getFamilies(); - } - - @Signature - public static List getFontNames() { - return Font.getFontNames(); - } - - @Signature - public static List getFontNames(String family) { - return Font.getFontNames(family); - } - - @Signature - public static Font getDefault() { - return Font.getDefault(); - } - - @Signature - public static Font of(String family, int size) { - return Font.font(family, size); - } - - @Signature - public static Font of(String family, int size, FontWeight fontWeight) { - return Font.font(family, fontWeight, size); - } - - @Signature - public static Font of(String family, int size, FontWeight fontWeight, boolean italic) { - return Font.font(family, fontWeight, italic ? FontPosture.ITALIC : FontPosture.REGULAR, size); - } - - @Signature - public static Font load(InputStream stream, double size) { - return Font.loadFont(stream, size); - } - - @Getter - public float getLineHeight() { - return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(getWrappedObject()).getLineHeight(); - } - - public static float getLineHeight(Font font) { - return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(font).getLineHeight(); - } - - @Signature - public float calculateTextWidth(String text) { - return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(text, getWrappedObject()); - } - - - public static float calculateTextWidth(String text, Font font) { - return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(text, font); - } -} +package org.develnext.jphp.ext.javafx.classes.text; + +import javafx.scene.text.Font; +import javafx.scene.text.FontPosture; +import javafx.scene.text.FontWeight; +import org.develnext.jphp.ext.javafx.JavaFXExtension; +import php.runtime.annotation.Reflection; +import php.runtime.annotation.Reflection.Getter; +import php.runtime.annotation.Reflection.Property; +import php.runtime.annotation.Reflection.Signature; +import php.runtime.env.Environment; +import php.runtime.lang.BaseWrapper; +import php.runtime.reflection.ClassEntity; + +import java.io.InputStream; +import java.util.List; + +@Reflection.Name(JavaFXExtension.NS + "text\\UXFont") +public class UXFont extends BaseWrapper { + interface WrappedInterface { + @Property String name(); + @Property String family(); + @Property String size(); + @Property String style(); + } + + public UXFont(Environment env, Font wrappedObject) { + super(env, wrappedObject); + } + + public UXFont(Environment env, ClassEntity clazz) { + super(env, clazz); + } + + @Signature + public void __construct(double size) { + __wrappedObject = new Font(size); + } + + @Signature + public void __construct(double size, String name) { + __wrappedObject = new Font(name, size); + } + + @Signature + public static List getFamilies() { + return Font.getFamilies(); + } + + @Signature + public static List getFontNames() { + return Font.getFontNames(); + } + + @Signature + public static List getFontNames(String family) { + return Font.getFontNames(family); + } + + @Signature + public static Font getDefault() { + return Font.getDefault(); + } + + @Signature + public Font withItalic() { + return withNameAndSize(getWrappedObject().getName(), getWrappedObject().getSize(), null, true); + } + + @Signature + public Font withRegular() { + return withNameAndSize(getWrappedObject().getName(), getWrappedObject().getSize(), null, false); + } + + @Signature + public Font withBold() { + return withNameAndSize(getWrappedObject().getName(), getWrappedObject().getSize(), true, null); + } + + @Signature + public Font withThin() { + return withNameAndSize(getWrappedObject().getName(), getWrappedObject().getSize(), false, null); + } + + @Signature + public Font withName(String name) { + return withNameAndSize(name, getWrappedObject().getSize()); + } + + @Signature + public Font withSize(int size) { + return withNameAndSize(getWrappedObject().getName(), size); + } + + @Signature + public Font withNameAndSize(String name, double size) { + return withNameAndSize(name, size, null, null); + } + + protected Font withNameAndSize(String name, double size, Boolean bold, Boolean italic) { + Font font = getWrappedObject(); + + FontWeight weight = bold != null && bold ? FontWeight.BOLD : FontWeight.THIN; + FontPosture posture = italic != null && italic ? FontPosture.ITALIC : FontPosture.REGULAR; + + if (font.getStyle().toUpperCase().contains("BOLD")) { + weight = FontWeight.BOLD; + } + + if (font.getStyle().toUpperCase().contains("ITALIC")) { + posture = FontPosture.ITALIC; + } + + return Font.font(name, weight, posture, size); + } + + @Signature + public static Font of(String family, int size) { + return Font.font(family, size); + } + + @Signature + public static Font of(String family, int size, FontWeight fontWeight) { + return Font.font(family, fontWeight, size); + } + + @Signature + public static Font of(String family, int size, FontWeight fontWeight, boolean italic) { + return Font.font(family, fontWeight, italic ? FontPosture.ITALIC : FontPosture.REGULAR, size); + } + + @Signature + public static Font load(InputStream stream, double size) { + return Font.loadFont(stream, size); + } + + @Getter + public float getLineHeight() { + return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(getWrappedObject()).getLineHeight(); + } + + public static float getLineHeight(Font font) { + return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(font).getLineHeight(); + } + + @Signature + public float calculateTextWidth(String text) { + return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(text, getWrappedObject()); + } + + + public static float calculateTextWidth(String text, Font font) { + return com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(text, font); + } +} diff --git a/jphp-gui-ext/src/main/resources/JPHP-INF/sdk/php/gui/text/UXFont.php b/jphp-gui-ext/src/main/resources/JPHP-INF/sdk/php/gui/text/UXFont.php index 43f1f26f..e2bd1596 100644 --- a/jphp-gui-ext/src/main/resources/JPHP-INF/sdk/php/gui/text/UXFont.php +++ b/jphp-gui-ext/src/main/resources/JPHP-INF/sdk/php/gui/text/UXFont.php @@ -1,98 +1,150 @@ -childrenUnmodifiable as $node) { - if ($node instanceof UXNode) { - $data = $node->id ? self::get($node, $layout, false) : null; - $callback($data, $node); - } - - if ($node instanceof UXTitledPane || $node instanceof UXScrollPane) { - if ($node->content instanceof UXParent) { - self::scan($node->content, $callback); - } - } else if ($node instanceof UXTabPane) { - if ($node->tabs->count) { - foreach ($node->tabs as $tab) { - if ($tab->content instanceof UXParent) { - self::scan($tab->content, $callback); - } - } - } - } else if ($node instanceof UXParent) { - self::scan($node, $callback); - } - } - } - - /** - * @param UXParent $layout - * @param callable $callback (array $data, UXNode $node) - */ - public static function scan(UXParent $layout, callable $callback) - { - foreach ($layout->childrenUnmodifiable as $node) { - if ($node instanceof UXData) { - $nd = self::getNode($layout, $node); - if ($nd) { - $callback($node, $nd); - } - } else if ($node instanceof UXTitledPane || $node instanceof UXScrollPane) { - if ($node->content instanceof UXParent) { - self::scan($node->content, $callback); - } - } else if ($node instanceof UXTabPane) { - if ($node->tabs->count) { - foreach ($node->tabs as $tab) { - if ($tab->content instanceof UXParent) { - self::scan($tab->content, $callback); - } - } - } - } else if ($node instanceof UXParent) { - self::scan($node, $callback); - } - } - } - - /** - * @param UXParent $parent - */ - public static function cleanup(UXParent $parent) - { - foreach ($parent->childrenUnmodifiable as $node) { - if ($node instanceof UXData) { - $nd = static::getNode($parent, $node); - - if (!$nd) { - $parent->children->remove($node); - } - } else if ($node instanceof UXTitledPane) { - if ($node->content instanceof UXParent) { - static::cleanup($node->content); - } - } else if ($node instanceof UXParent) { - static::cleanup($node); - } - } - } - - /** - * @param UXNode $node - * - * @param UXPane|UXParent $layout - * - * @param bool $create - * @return UXData - * @throws IllegalArgumentException - */ - public static function get(UXNode $node, UXParent $layout = null, $create = true) - { - $factoryId = $node->data('-factory-id'); - - if ($factoryId) { - $d = $node->data('-factory-data'); - - if ($create && !$d) { - $d = new UXData(); - $node->data('-factory-data', $d); - } - - return $d; - } - - if (!$node->id) { - throw new IllegalArgumentException("The node must have id value"); - } - - if (!$layout) { - $layout = $node->parent; - } - - if (!$layout) { - throw new IllegalArgumentException("The node must have parent value"); - } - - $data = $layout->lookup('#data-' . $node->id); - - if (!$data && $create) { - $data = new UXData(); - $data->id = 'data-' . $node->id; - - $layout->add($data); - } - - return $data; - } - - /** - * @param UXParent $layout - * @param UXData $data - * - * @return UXNode - */ - protected static function getNode(UXParent $layout, UXData $data) - { - $id = $data->id; - - if (Str::startsWith($id, 'data-')) { - return $layout->lookup('#' . Str::sub($id, 5)); - } - - return null; - } - - /** - * @param UXNode $node - * - * @throws IllegalArgumentException - */ - public static function remove(UXNode $node) - { - $data = static::get($node); - - $parent = $data->parent; - - if (isset($parent->children)) { - $parent->children->remove($data); - } - } +childrenUnmodifiable as $node) { + if ($node instanceof UXNode) { + $data = $node->id ? self::get($node, $layout, false) : null; + $callback($data, $node); + } + + if ($node instanceof UXTitledPane || $node instanceof UXScrollPane) { + if ($node->content instanceof UXParent) { + self::scan($node->content, $callback); + } + } else if ($node instanceof UXTabPane) { + if ($node->tabs->count) { + foreach ($node->tabs as $tab) { + if ($tab->content instanceof UXParent) { + self::scan($tab->content, $callback); + } + } + } + } else if ($node instanceof UXParent) { + self::scan($node, $callback); + } + } + } + + /** + * @param UXParent $layout + * @param callable $callback (array $data, UXNode $node) + */ + public static function scan(UXParent $layout, callable $callback) + { + foreach ($layout->childrenUnmodifiable as $node) { + if ($node instanceof UXData) { + $nd = self::getNode($layout, $node); + if ($nd) { + $callback($node, $nd); + } + } else if ($node instanceof UXTitledPane || $node instanceof UXScrollPane) { + if ($node->content instanceof UXParent) { + self::scan($node->content, $callback); + } + } else if ($node instanceof UXTabPane) { + if ($node->tabs->count) { + foreach ($node->tabs as $tab) { + if ($tab->content instanceof UXParent) { + self::scan($tab->content, $callback); + } + } + } + } else if ($node instanceof UXParent) { + self::scan($node, $callback); + } + } + } + + /** + * @param UXParent $parent + */ + public static function cleanup(UXParent $parent) + { + if (UXApplication::isUiThread()) { + foreach ($parent->childrenUnmodifiable as $node) { + if ($node instanceof UXData) { + $nd = static::getNode($parent, $node); + + if (!$nd) { + $parent->children->remove($node); + } + } else if ($node instanceof UXTitledPane) { + if ($node->content instanceof UXParent) { + static::cleanup($node->content); + } + } else if ($node instanceof UXParent) { + static::cleanup($node); + } + } + } + } + + /** + * @param UXNode $node + * + * @param UXPane|UXParent $layout + * + * @param bool $create + * @return UXData + * @throws IllegalArgumentException + */ + public static function get(UXNode $node, UXParent $layout = null, $create = true) + { + $factoryId = $node->data('-factory-id'); + + if ($factoryId) { + $d = $node->data('-factory-data'); + + if ($create && !$d) { + $d = new UXData(); + $node->data('-factory-data', $d); + } + + return $d; + } + + if (!$node->id) { + throw new IllegalArgumentException("The node must have id value"); + } + + if (!$layout) { + $layout = $node->parent; + } + + if (!$layout) { + throw new IllegalArgumentException("The node must have parent value"); + } + + $data = $layout->lookup('#data-' . $node->id); + + if (!$data && $create) { + $data = new UXData(); + $data->id = 'data-' . $node->id; + + $layout->add($data); + } + + return $data; + } + + /** + * @param UXParent $layout + * @param UXData $data + * + * @return UXNode + */ + protected static function getNode(UXParent $layout, UXData $data) + { + $id = $data->id; + + if (Str::startsWith($id, 'data-')) { + return $layout->lookup('#' . Str::sub($id, 5)); + } + + return null; + } + + /** + * @param UXNode $node + * + * @throws IllegalArgumentException + */ + public static function remove(UXNode $node) + { + $data = static::get($node); + + $parent = $data->parent; + + if (isset($parent->children)) { + $parent->children->remove($data); + } + } } \ No newline at end of file