Проблеми, з якими ми зіткнулися під час оновлення інтерфейсу PVS-Studio

<img src=«habrastorage.org/getpro/habr/post_images/610/0d5/bc4/6100d5bc41e18b1a4c275465d17aa25e.png» alt=«Picture » 2" align=«left»/>
У нещодавно вийшла нової версії PVS-Studio 6.10 був суттєво оновлений графічний користувальницький інтерфейс Visual Studio плагінів і Standalone версії. Попередня версія інтерфейсу, незважаючи на постійну еволюцію (додавалися і зникали нові кнопки і пункти меню), проіснувала практично 6 років без суттєвих змін, вперше з'явившись в PVS-Studio версії 4.0 у 2010 році.

У даній замітці ми хочемо розповісти, які причини спонукали нас замислитися про необхідність зміни інтерфейсу, і з якими проблемами ми зіткнулися в процесі роботи над ним.

Проблеми старого інтерфейсу PVS-Studio, і чому ми вирішили його поміняти
Для початку трохи історії. Окреме вікно PVS-Studio з'явилося в Visual Studio плагіні починаючи з 4-ої версії аналізатора. Попередні версії використовували для виведення діагностичних повідомлень стандартне вікно Error List, однак наші вимоги швидко переросли можливості цього вікна. Крім неможливості додавати свої фільтри, контекстні меню, кнопки і т. п., головною причиною, що спонукала нас реалізувати власне вікно для повідомлень PVS-Studio, стала продуктивність Error List'а. При запису в нього хоча б декількох тисяч повідомлень, працювати з ним ставало неможливо — студія підвисала навіть просто при спробі здійснити його прокручування.

Звичайно, можна сказати: аналізатор, який видає тисячі повідомлень, це поганий аналізатор. Однак, слід враховувати, що нашими першими діагностиками були помилки портування C++ програм на 64-бітну платформу, і, по своїй природі, такі помилки можуть бути досить численними, особливо на реальних великих проектах. По секрету можу сказати, що нашим «анти-рекорд» був звіт на ~250 000 повідомлень! Тут же хочу заспокоїти наших користувачів — сучасна версія PVS-Studio такого собі зазвичай не дозволяє, тим більше зараз у нас з'явилися такі концепції, як «рівні важливості» помилок і різні способи легко масово пригнічувати або відключати невдалі спрацьовування (які неминуче зустрічаються в рамках методології статичного аналізу). Однак, в далекому 2010 році всього цього ще не було, і «гальма» інтерфейсу були як ніколи актуальні.

Перші версії нашого плагіна з окремим вікном підтримували версій Visual Studio 2005 і 2008. Потрібно сказати, що сучасна Visual Studio також не стоїть на місці, і проблема з відображенням великого числа повідомлень в стандартному Error List'е у неї вже можливо і не так актуальна, але переваги окремого «вікна виводу» все одно очевидні. Забавно тут провести паралель з вбудованим C++ аналізатором Visual Studio — у певний період (здається, на версіях 2010 — 2012, але я можу помилятися), цей аналізатор також для відображення результатів своєї роботи використовував «власне», окреме вікно виведення. Однак, в останніх версіях Visual Studio повернулася до відображення результатів в стандартному вікні Error List. Про причини, з яких, на наш погляд, розробники Visual Studio це зробили, я розповім, коли буду описувати наше нове вікно.

Як я вже згадав вище, перші версії вікна PVS-Studio робилися для 2005 та 2008 версій середовища Visual Studio. Таким чином, при розробці початкового дизайну нашого вікна, ми орієнтувалися на дизайн стандартного Error List'а саме з цих версій IDE. Цим в основному і пояснюється той стиль іконок, який ми взяли на озброєння. Незважаючи на те, що в сучасних версіях Visual Studio наше вікно підтримувало всі новомодні колірні теми оформлення, іконки в нього залишилися ще з тих часів. Ось так виглядали основні компоненти нашого інтерфейсу до «рестайлінгу»:

<img src=«habrastorage.org/getpro/habr/post_images/fb6/3c3/2db/fb63c32db28375503c0d4275cb1b6a36.png» alt=«Picture » 11"/>
Малюнок 1 — старий інтерфейс PVS-Studio, Visual Studio 2015 вікно виводу і головне меню)

Які ж проблеми у нашого інтерфейсу, крім суто «естетичних»? Напевно, головною нашою проблемою, а точніше проблемою, що доставляє незручності нашим користувачам, є інтуїтивність інтерфейсу. Навіть такі, здавалося б, базові можливості, як розмітка помилкових спрацьовувань через контекстне меню, або диференціація повідомлень за ступенем їх важливості, часто були для наших користувачів неочевидними і викликали питання. Нерідкою є ситуація, при якій користувач вважає найбільш «небезпечними» повідомлення 3-його рівня. Іншою проблемою є загальна «громіздкість» — занадто багато написів, незрозумілих скорочень і кнопок, складно щось знайти.

В новому інтерфейсі ми постаралися вирішити ці проблеми, а наскільки у нас це вийшло — можна дізнатися далі.

Новий дизайн основного вікна
Перед тим, як починати писати код, ми звернулися до професійного дизайнера із завданням створення концепції нового інтерфейсу. Як я згадував раніше, наше вікно повторювало концепцію стандартного Error List'а, і, відповідно, центральною його частиною був класичний «грід» — таблиця зі стовпцями і рядками. Ми хотіли поекспериментувати і спробувати відмовитися від «класичної» формули, тим більше зараз в моді мінімалістичність, і сама Visual Studio схильна даними тенденціям у своєму інтерфейсі. В якості нового «натхнення» ми вирішили спробувати використовувати знову елементи Visual Studio — вікно нотифікацій та вікно виведення результатів вбудованого C++ аналізатора.

<img src=«habrastorage.org/getpro/habr/post_images/96d/d3d/80e/96dd3d80e0328c039afeccb0ad962d3b.png» alt=«Picture » 3"/>
Рисунок 2 — вікно вбудованого статичного аналізу (Visual Studio 2012) і вікно нотифікацій (Visual Studio 2013)

Як видно з картинки, обидва вікна максимально мінімалістичні — не містять нічого, крім тексту повідомлення якого-небудь ідентифікатора (код або маркер). На лівому вікні є також поля для пошуку/фільтрації. Також, на відміну від Error List, обидва вікна орієнтовані швидше на вертикальне, а не горизонтальне розташування.

І тут я хочу повернутися до того, що вже згадував вище — в 2015 студії розробники Microsoft чомусь відмовилися від свого «модного» нового вертикального вікна статичного аналізу (на зображенні зліва) на користь «старого доброго» Error List'а. Чому вони так зробили? На мій погляд, а також з досвіду власного використання цього нового вікна — просто тому, що цим вікном було незручно користуватися. В вертикальної таблиці на екран влазило мало повідомлень, не було можливості відсортувати їх за яким-небудь критерієм (наприклад, за кодом або по файлу), а за «розкриття» картки з повідомленням, воно взагалі часом займало весь екран.

«Погравши» з різними варіантами дизайну, ми прийшли в результаті до того ж висновку — повідомлення аналізатора (як і, наприклад, попередження компілятора) зручніше переглядати та аналізувати в класичному горизонтальному «гріді». Так, інтерфейс нотифікацій (на малюнку праворуч) зручний, коли потрібно видати два-три повідомлення, що вимагають уваги, але коли користувачеві потрібно працювати з десятками (а іноді сотнями і навіть тисячами) повідомлень — переваги таблиці стають очевидні. Звичайно, після початкової настройки, розробникам зазвичай доводиться мати справу одночасно з декількома повідомленнями на новому коді, якщо, звичайно, статичний аналізатор використовується правильно, тобто регулярно. Але етап початкової настройки не менш важливий, і часто від правильності його проведення залежить успішність подальшого використання аналізатора. Тим не менш, у вікні нотифікацій ми почерпнули цікаву ідею візуальної диференціації «важливості» повідомлень — з допомогою кольорової смужки.

Після того, як ми визначилися з загальним напрямком, потрібно було вибрати технологічну основу для інтерфейсу. Попередня версія нашого інтерфейсу використовувала «старий добрий» Windows Forms — це було пов'язано з необхідністю підтримки Visual Studio 2005 і 2008. З урахуванням того, що сам Visual Studio плагін розробляється на C#, Visual Studio не є кроссплатформної і, напевно, головне — що сама Visual Studio використовує технологію WPF, найбільш логічним здається використовувати той же WPF і для оновленого інтерфейсу. Тим не менше, навіть незважаючи на те, що вся внутрішня логіка плагіна і використовувані ним структури даних безпосередньо на інтерфейс не «зав'язані», ми вирішили в поточній версії спробувати спочатку провести «косметичний ремонт», тобто просто «перефарбувати» поточний інтерфейс у відповідності з оновленим дизайном, залишивши всі нижні компоненти без змін. На жаль, реальний світ диктує свої умови, і іноді доводиться розставляти пріоритети в тому, що хочеться зробити, і те, що зробити треба. Тим більше, такий косметичний ремонт можна зробити дуже малими силами і за короткий термін.

Потрібно визнати, що базових можливостей WinForms нам вже починає не вистачати — навіть така, здавалося б, невелика «косметична» правка зажадала реалізації в коді кількох «милиць», не помітних для користувачів, але вже ускладнюють подальші підтримку і розвиток інтерфейсу. Наприклад, довелося «попрацювати» з новими кнопками рівнів (з смужкою кольору) при відображенні на toolstrip панелі. Стандартний toolstrip в WinForms сам відповідає за малювання своїх елементів, але при хостингу користувальницького контрола, рендеринг цього контрола доводиться перекладати на нього самого (це було особливо актуально для нас в плані підтримки колірних схем). Використання WinForms також змушує нас для підтримки колірних схем користуватися досить архаїчним VS SDK інтерфейсом GetVSSysColorEx, і самостійно «розфарбовувати» наші компоненти, а також відловлювати момент перемикання колірної теми. Для WPF компонентів Visual Studio пропонує більш зручний механізм підхоплення квітів через динамічні ресурси, безпосередньо в розмітки XAML.

У підсумку, думаю, ми можемо з великою часткою впевненості стверджувати, що наступна (після обновлення) версія інтерфейсу PVS-Studio буде повністю заснована на WPF. Зараз же, нашою метою, як і для минулого ітерації інтерфейсу, було збереження «автентичності» по відношенню до стандартних вікон Visual Studio. Вийшов у нас результат можна побачити нижче:

Рисунок 3 - оновлений інтерфейс PVS-Studio (вікно виводу і головне меню)
Малюнок 3 — оновлений інтерфейс PVS-Studio (вікно виводу і головне меню)

Пункти меню, іконки і граблі
Старі іконки плагіна PVS-Studio були далекі від ідеалу, а точніше, від стандартної «теми оформлення» в Visual Studio, тому було прийнято рішення їх замінити. Основною вимогою для нових іконок було їх відповідність єдиному стилю і хороший контраст для всіх колірних схем Visual Studio.

Визначившись з сетом іконок, ми приступили до розробки. Першою проблемою, з якою ми зіткнулися, стало, як не дивно, безпосередньо відображення іконок в основному меню Visual Studio. Ви скажіть: «Почекайте, адже ви вже показували свої іконки в цьому меню, починаючи з першої версії PVS-Studio!». Дійсно, це так, але використовуваний нами раніше метод не підходив для наших цілей. Уточню, що для завдання іконок ми використовували єдиний механізм розширень Visual Studio для створення пунктів меню — vsct файли (про це можна детальніше почитати тут). Що ж нас не влаштовувало в цьому варіанті? Для початку, іконки можна було задати тільки один раз — при завантаженні плагіна студією. Ми ж хотіли імітувати поведінку стандартних іконок студії, тобто перефарбовувати їх в залежності від вибраної колірної схеми (як виявилося потім, це вимога було зайвим — студія вміє це робити сама). По-друге, vsct файл не вміє (або можливо ми не вміємо в рамках vsct файлу) використовувати зображення іконок альфа-канал, з-за чого вони виглядали вельми непривабливо.

Постало питання: як нам ставити картинку для іконки пункту меню програмно, так і чи можна це зробити взагалі? Після довгих пошуків вдалося знайти стороннє розширення Visual Studio, яке вміло це робити. А дослідження його вихідного коду дозволило нам знайти відповідь на поставлене вище питання. Все виявилося дуже просто:
var commandBars = (CommandBars)DTE.CommandBars;
var menuBar = commandBars[menuBarKey];
var pvsBar = menuBar.Controls["PVS-Studio"] 
as CommandBarPopup;
...
cmdBtnControl.Picture = ImageHelper.BitmapToStdPicture(bmp);

Також у нас виникло занепокоєння, що такий метод «зламається», якщо користувач захоче (а чому б і ні?) перейменувати пункт меню PVS-Studio, адже Visual Studio дозволяє це робити. Однак, ці побоювання виявилися марними — внутрішнє ім'я об'єктів commandBar не змінюється.

Вирішивши питання з динамічним відображенням іконок, ми реалізували алгоритм, за яким монохромна іконка закрашивалась б в колір, вибраний з активної теми Visual Studio. Ми инвертировали всі іконки в ресурсах плагіна в білий колір і написали простий алгоритм перетворення, який множив колір кожного пікселя зображення на необхідний нам:
public static void Colorize(ref Bitmap img, Color color)
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
// Обходимо кожен піксель зображення в циклі
// І множимо його колір на колір тексту у поточній схемі
var pixel = img.GetPixel(x, y);
var r = (byte)(((float)pixel.R) * ((float)color.R / 255f));
var g = (byte)(((float)pixel.G) * ((float)color.G / 255f));
var b = (byte)(((float)pixel.B) * ((float)color.B / 255f));
img.SetPixel(x, y, Color.FromArgb(pixel.A, r, g, b));
}
}
}

На виході ми отримували ось такий результат:

Рисунок 4 - Приклад роботи алгоритму колоризації іконок.
Рисунок 4 — Приклад роботи алгоритму колоризації іконок.

Однак, ми виявили несподівану поведінку — у разі вибору, наприклад, «червоної» теми оформлення Visual Studio, іконка відображалася коректно. Коректно вона відображалася і в «світлій» схемою. У «темній» ж схемою іконки залишалися чорними, а не ставали білими, як ми очікували. Виявилося, що студія сама вміє інвертувати певні кольори картинки в залежності від «яскравості» фону в обраній колірній схемі — попередні експерименти з колоризацією іконок виявилися марними. Студія все зробила за нас сама. Незважаючи на це, ми все-таки вирішили залишити описаний вище метод програмного завдання іконок з-за проблем з альфа-каналом.

Аналогічно, в нашому вікні виводу повідомлень PVS-Studio ми поміняли всі значки і іконки на відповідні з того ж набору. Однак, якщо іконки в меню змінювали колір в залежності від колірної схеми Visual Studio автоматично, значки у вікні плагіна залишалися у вихідному вигляді для всіх колірних схем.

Рисунок 5 - Проблеми з відображенням іконок в темній колірній схемі Visual Studio.
Малюнок 5 — Проблеми з відображенням іконок в темній колірній схемі Visual Studio.

Ми задалися питанням, чи можна використовувати Visual Studio SDK для студійного застосування алгоритму колоризації для наших іконок. Результат не змусив нас довго чекати. Через кілька хвилин пошуку ми натрапили на метод GetThemedBitmap в класі ImageThemingUtilities простору імен Microsoft.VisualStudio.PlatformUI. Він робив саме те, що нам і було потрібно!

Рисунок 6 - Коректне відображення іконок в нашому вікні для темної теми Visual Studio.
Малюнок 6 — Коректне відображення іконок в нашому вікні для темної теми Visual Studio.

Ще одна проблема, з якою ми зіткнулися при зміні іконок — це їх розмиття на DPI відмінному від 100%. Це відбувалося, оскільки всі іконки мали розмір 16х16 пікселів. Дану проблему нам вдалося частково перемогти, використовуючи спочатку іконки розміром 64x64. У такому разі VisualStudio автоматично стискала їх до потрібного розміру. Але і в цьому варіанті все виявилося не зовсім гладко. Тепер при 100% DPI з'явилося невелике розмиття. В результаті було прийнято рішення використовувати саме зображення розміром 64x64, так як на DPI відмінних від 100% це давало найбільш прийнятний результат, а при 100% DPI, розмиття було практично не помітним.

Так само при DPI 115% було помічено обрізання правого краю іконки на кілька пікселів. Спроби програмно додавати кілька пікселів справа (щоб зображення мало розмір 64x68) теж не увінчалися успіхом. Іконки в Visual Studio стискалися назад до квадратного співвідношення сторін, і хоч обрізання і вдалося перемогти, але розмиття зросла в рази. В результаті ми просто додали кілька порожніх пікселів в кожну іконку, залишивши розмір 64х64. Це рішення забезпечило мінімальну розмиття (практично непомітний для очей) і виключило обрізання правого боку біля іконок.

Висновок
Незважаючи на здаються значні зовнішні зміни, «під капотом» інтерфейс PVS-Studio фактично залишився незмінним. Ми сподіваємося, що для наших старих користувачів новий інтерфейс залишиться «знайомим», а для нових користувачів він буде більш інтуїтивно зрозумілий і приємний. Ну і звичайно, що він буде «гарніше» в очах всіх наших користувачів. Наскільки у нас це вийшло — судити вам.


Якщо хочете поділитися цією статтею з англомовної аудиторією, то прошу використовувати посилання на переклад: Ivan Kishchenko, Paul Eremeev. Issues we faced when renewing PVS-Studio user interface.

Прочитали статтю і є питання?Часто до наших статей задають одні і ті ж питання. Відповіді на них ми зібрали тут: Відповіді на питання читачів статей про PVS-Studio, версія 2015. Будь ласка, ознайомтеся зі списком.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.