مرحباً بالجميع ، لفترة طويلة لم أكتب مقالة حول حياة المشروع على المحور
Consulo هي شوكة من IntelliJ IDEA Community Edition التي تدعم .NET (C #) ، Java
لنبدأ
س: Consulo UI API - ما هو؟
ج: هذه مجموعة من واجهات برمجة التطبيقات لإنشاء واجهة مستخدم. في الواقع ، مجموعة بسيطة من الواجهات التي تكرر مكونات مختلفة - Button ، RadionButton ، Label ، إلخ.
س: ما هو الغرض من إنشاء مجموعة أخرى من واجهات برمجة تطبيقات واجهة المستخدم إذا كان هناك Swing بالفعل (نظرًا لأن واجهة مستخدم IDEA تستخدم Swing لعرض الواجهة)
ج: لهذا ، دعونا نتعمق في الفكرة التي اتبعتها أثناء العمل على واجهة برمجة تطبيقات Consulo UI. نظرًا لأنني المساهم الرئيسي والوحيد تقريبًا في مشروع Consulo ، فقد أصبح من الصعب بالنسبة لي بمرور الوقت الحفاظ على عدد المشاريع التي أصبحت الآن (حوالي 156 مستودعًا). كان هناك سؤال حول تحليل الشفرة الجماعية ، ولكن من المستحيل القيام بذلك في إطار مثيل IDE واحد على منصة سطح المكتب ، واستخدام تجربة JetBrains حيث يحتوي مشروع واحد في نهاية المطاف على جميع المكونات الإضافية التي لم أرغب في ممارستها لعدد من الأسباب.
نشأت الفكرة من التحليل على خادم الويب. لم يكن "التحليل المعتاد" يناسبني كثيرًا على خادم الويب ، كنت أرغب في إنشاء IDE للويب (على الأقل للقراءة فقط في البداية) - في حين لا يزال لدي نفس الوظائف الموجودة على سطح المكتب.
يمكنك القول أن هذا يكرر قليلاً من Upsource ، والفكرة نفسها متشابهة - لكن النهج مختلف تمامًا.
ثم جاءت اللحظة - عندما كانت الفكرة ، ولكن لم يكن من المعروف كيف نفعل ذلك. كانت لدي خبرة في استخدام إطارات GWT و Vaadin - لم أكن أرغب في استخدام أطر أخرى غير Java لتوليد JS (جيد أو عادي).
لقد استغرقت شهرًا للبحث في هذا. لقد كان اختبار لقدراتي في هذا الجزء. في البداية ، استخدمت GWT فقط - للحصول على معلومات ، استخدمت RPC المدمج.
كان هناك هدف بسيط - كان المشروع مفتوحًا بالفعل ، وكان من الضروري فقط عرض علامات تبويب Project Tree + Editor . في هذه الحالة ، يجب أن يكون كل شيء مشابهًا لإصدار سطح المكتب.
على الفور كانت هناك مشاكل مع الواجهة الخلفية المصنوعة حديثًا. على سبيل المثال ، استخدام EventQueue للإجراءات الداخلية
EventQueue باختصار ، إنه دفق واجهة مستخدم (AWT ، Swing) ؛ كل ما يتعلق بواجهة المستخدم يحدث فيه تقريبًا - العرض ومعالجة نقرة زر وما إلى ذلك.
تاريخيًا ، في IDEA ، يجب تنفيذ إجراءات الكتابة دائمًا في سلسلة واجهة مستخدم.
إجراء الكتابة هو سجل لملف ، أو تغييرات على بعض الخدمات (على سبيل المثال ، إعادة تسمية وحدة نمطية)
في البداية ، يمكن تجاهل مشكلة EventQueue - ولكن بعد ذلك ظهرت مشاكل أخرى. على سبيل المثال ، الرموز العادية. تخيل أن لدينا شجرة مشروع
- [] اسم المشروع
- [] src
- [] اختبار
- [] build.gradle
ولكل ملف نحتاج إلى تحميل وعرض صورة. نظرًا لأننا نعمل داخل كود Swing ، فإننا نستخدم فئة javax.swing.Icon . المشكلة هي أنها مجرد واجهة - لديها العديد من التطبيقات المختلفة
- رمز الصورة هو رمز يلتف ببساطة الصورة (أي صورة عادية من نظام الملفات)
- الأيقونة ذات الأيقونة ذات الطبقات التي تتكون من أيقونة أو أكثر مكدسة فوق بعضها البعض
- أيقونة معطل - أيقونة مع مرشح رمادي مطبّق
- أيقونة شفافة - أيقونة مع الشفافية المحددة
- وغيرها الكثير
نتيجة لذلك ، من أجل إظهار الرمز في المتصفح ، تحتاج إلى دعم حديقة الحيوان بأكملها (وكلها تقريبًا دفعة واحدة). إحدى المشاكل ذات الصلة هي أن رمزًا غير معروف تمامًا لك للملف قد يأتي (على سبيل المثال ، يتم رسم رمز بكسل بكسل داخل بعض المكونات الإضافية) - وما شابه ذلك يجب تجاهلها.
مع طريقة عكاز (حسنًا ، حيث بدونها) - تم اتخاذ قرار. من المضحك التحقق من المثال الذي نحتاجه - وتجاهل جميع الأنواع الأخرى.
بعد فترة ، تم تقديم الدعم للتنقل في نظام الملفات أو فتح ملف أو تمييز بناء الجملة أو التحليل الدلالي أو معلومات سريعة عن المستندات أو التنقل لمراجع التعليمات البرمجية (تم دعم مجموعة مثل Ctrl + B أو Ctrl + MouseClick1). في الجوهر ، كان المحرر مشابهًا جدًا لمنصة سطح المكتب.
كيف يبدو:

لذلك - لجعل واجهة الويب ممكنة مع قوتي. لكنها كانت مهمة صعبة للغاية - كان لا بد من إعادة بنائها. ثم جاء فادين للإنقاذ.
قررت إعادة تنفيذ GWT لاستخدام إطار Vaadin. تبين أن هذا الاختبار كان سيئًا للغاية (كان الأداء متدهورًا جدًا) - أثرت تجربتي في استخدام Vaadin بشكل أكبر ، ورفضت هذا الخيار (حتى لقد أجريت إعادة ضبط صارمة على وجبة الغداء الحالية لنسيانها: D).
لكن تجربة استخدام Vaadin كانت مفيدة لي طوال الوقت ، نشأت الفكرة - لتوحيد واجهة المستخدم بحيث يمكنك كتابة رمز واحد ، ولكن الحصول على نتائج مختلفة في الإخراج ، اعتمادًا على النظام الأساسي.
سبب آخر لتوحيد واجهة المستخدم هو حديقة الحيوانات الكاملة لمكونات Swing داخل منصة IntelliJ. مثال على هذه المشكلة هو تطبيقين مختلفين تمامًا لعلامات التبويب .


افصل منطق واجهة المستخدم:
- الواجهة الأمامية - مجموعة من الواجهات لكل عنصر ، على سبيل المثال consulo.ui.Button # create ()
- تنفيذ يعتمد على الواجهة الخلفية للمنصة
- Swing - تنفيذ سطح المكتب
- WGWT - تنفيذ الويب
ما هو WGWT ؟ اختصارات ل Wrapper GWT. هذا إطار عمل مكتوب ذاتيًا - قام بتخزين حالة المكون وإرساله عبر WebSocket إلى المستعرض (والذي بدوره أدى إلى إنشاء html). كتب بعين العين على فادين (نعم نعم - عكاز آخر).
مر الوقت - وبالفعل يمكنني تشغيل واجهة مستخدم تجريبية تعمل بنفس الطريقة على سطح المكتب وفي المتصفح

لقد استخدمت أيضًا Vaadin في العمل بالتوازي ، حيث يعد هذا أحد أرخص الخيارات لبناء واجهة مستخدم ويب إذا كنت تستخدم Java. لقد درست Vaadin أكثر فأكثر - وقررت إعادة كتابة WGWT إلى Vaadin مرة أخرى ، ولكن مع بعض التصحيحات.
ما هي التعديلات:
- رفض استخدام جميع مكونات Vaadin تقريبًا. كانت هناك عدة أسباب - كان أحدها محدودًا جدًا من المكونات (كان التخصيص محدودًا).
- باستخدام المكونات الموجودة من إطار عمل WGWT الخاص بي ؛ أي تنفيذها GWT
- كان هناك أيضًا تصحيحًا سمح لك بكتابة التعليقات التوضيحية Connect بدون ارتباط مباشر بمكون الخادم (تم ذلك بشكل أكبر لبنية المشروع ، لتجنب توفر فئات الخادم داخل رمز العميل)
ونتيجة لذلك ، اتضح مثل هذا:
- الواجهة الأمامية - مجموعة من الواجهات لكل عنصر ، على سبيل المثال consulo.ui.Button # create ()
- الخلفية - التنفيذ الحالي اعتمادًا على النظام الأساسي
- Swing - تنفيذ سطح المكتب
- فادين - تنفيذ الويب
- Android؟ - من أجل احتراق الهاتف في بداية التطبيق: D حتى الآن ، فقط على مستوى فكرة أنه سيكون من الممكن استخدام رمز موجود لنقله إلى Android (لأنه لن يكون هناك ربط بـ Swing)
وهكذا ولدت واجهة برمجة التطبيقات Consulo UI API الحالية.
أين سيتم استخدام Consulo UI API؟
- في جميع الإضافات. سيتم "حظر" AWT / Swing (لا مزيد من java.awt.Color ) أثناء التجميع (سيتم عمل معالج javac - لاحقًا ، قد لا يكون ضروريًا على الإطلاق مع وصول java 9). مجموعتك من المكونات ليست حلا سحريا ، أفهم ذلك. في الوقت الحالي ، يمكنك إنشاء مكون واجهة المستخدم المخصص الخاص بك ، حتى الآن فقط على جانب Swing (وفي مثل هذه الحالات سيكون من الضروري إضافة تبعية إلى البرنامج المساعد consulo.destop لتجنب المشاكل على خادم الويب). لم يتم إنشاء مكونات Vaadin على جانب البرنامج المساعد بعد - ستكون هذه مهمة بسيطة.
- على جانب النظام الأساسي ، هذه هي الإعدادات / التفضيلات ، تشغيل التكوينات ، المحرر - بشكل أساسي الواجهة الكاملة التي تنتقل إلى JFrame.
ما هي المشاكل؟
- غير متوافق تمامًا مع كود AWT / Swing (هناك فئة عكاز TargetAWT / TargetVaadin التي لديها طرق لتحويل المكونات ، ولكن لا يمكن الوصول إلى هذه الفئات للمكونات الإضافية).
لا يمكن عرض جميع مكونات Swing في المتصفح - ونتيجة لذلك ، تحتاج إلى إعادة كتابة كل هذا الرمز.
في كل مكان تقريبًا ، يتم دعم واجهة برمجة تطبيقات Consulo UI بالفعل داخل النظام الأساسي - وهذا يسمح لك بالفعل باستخدام إطار عمل واجهة المستخدم الجديد داخل المكونات الإضافية وليس فقط. - إن ارتباط منصة IntelliJ القوي بـ Swing ، مدفون بعمق لدرجة أنه بدون العكاز "التالي" ، لا يمكنك حفره (
)
بعد مرور بعض الوقت
يعمل هذا الرمز بنفس الطريقة على كلا النظامين الأساسيين.
عمله على سطح المكتب:

عمله في المتصفح:

بخصوص المشاكل المذكورة أعلاه:
- أيقونات. تم تقديم فئة consulo.ui.image.Image ، وهي صورة من نظام الملفات (وليس فقط). يمكنك استخدام طريقة consulo.ui.image.Image # create (java.net.URL) لتحميل صورة.
على منصة سطح المكتب - يتم تحميل الرموز كما تم تحميلها في وقت سابق ، والآن نوع العودة هو SwingImageRef (اسم الفئة القديمة - سابقًا consulo.ui.image.Image كان يسمى consulo.ui.ImageRef) - واجهة ترث javax.swing.Icon و consulo.ui صورة. صورة. ستتم إزالة هذه الواجهة لاحقًا (يرجع وجودها إلى ترحيل مبسط إلى نوع جديد)
على منصة الويب - يتم تخزين عنوان URL داخل الكائن ، وهو معرّف للعرض في الواجهة (عبر URL - / app / uiImage = URLhashCode )
تم إدخال فئة ImageEffects. لديها في حد ذاتها الطرق اللازمة لإنشاء الرموز المشتقة. على سبيل المثال ، #grayed (صورة) سيعرض رمزًا بفلتر رمادي ، و # شفاف (صورة) رمز شفاف.
أي أن حديقة الحيوان بأكملها الموضحة أعلاه قد تم دفعها إلى إطارات ضيقة.
سيتم أيضًا تقديم الدعم للعرض اليدوي للعناصر (حسنًا ، حيث بدون ذلك). طريقة ImageEffects # قماش (الارتفاع الدولي ، العرض الدولي ، المستهلك <لوحة الرسم> مستهلك الرسم) ستعيد رمزًا سيتم رسمه من خلال Canvas2D
على سطح المكتب - سيتم استخدام المجمع فوق Graphics2D العادي من Swing
على الويب - سيتم حفظ كل مكالمة إلى أساليب Canvas2D ، ثم يتم نقلها إلى المتصفح حيث سيتم استخدام اللوحة القماشية الداخلية من المتصفح
- اكتب الإجراء في مؤشر ترابط واجهة المستخدم. اووو لا يوجد حل لهذه المشكلة حتى الان. في الوقت الحالي - يوجد إجراء نموذجي للكتابة في سلسلة المحادثات الخاصة ، ولكن حتى الآن فقط على النظام الأساسي للويب ، يلزم تغيير الكثير داخل النظام الأساسي من أجل "طرحه" على سطح المكتب.
- تم توحيد واجهة المستخدم - لا توجد حديقة حيوانات للعناصر البسيطة
ظهرت مشكلة جديدة أيضًا - تمنع مربعات حوار Swing سلسلة التنفيذ أثناء العرض. نتيجة لذلك ، تحب IDEA كتابة التعليمات البرمجية في هذا النموذج:
DialogWrapper wrapper = ...; int value = wrapper.showAndGet(); if(value == DialogWrapper.OK) { ... }
في الوقت نفسه ، لا يؤدي عرض مربعات الحوار في Vaadin إلى حظر سلسلة التنفيذ.
لتجنب الارتباك مع العرض المتزامن وغير المتزامن لمربعات الحوار ، تم اختيار خيار غير متزامن (يجب إعادة التفكير في الكود أعلاه وإعادة بنائه).
الملخص
بعد فترة ، لدي نموذج أولي لتطبيق ويب.

حتى الآن هذا نموذج أولي يتحرك نحو إطلاقه - لكنه لن يكون سريعًا (للأسف).