четверг, 7 июня 2012 г.

ScreenWeather - погодный информер с Metro-подобным интерфейсом

 Эта запись - дневник разработки. В ней я хотел бы осветить подробности создания программы: от возникновения идеи до её реализации. Если Вы пришли сюда исключительно чтобы скачать программу, то смело листайте в конец записи (а еще лучше сюда (версия 2.0), там приведена ссылка на загрузку.


 День первый. Идея.

"Идея. Она живуча и очень заразна." (К/ф Начало).
 Всё началось с того, что мои родители перед походом на дачу смотрели погоду, чтобы узнать, не застанет ли их дождь и чтобы знать, стоит ли поливать участок или же дождь сделает это за них. Для этих целей у нас был только один виджет погоды, и он не всегда соответствовал действительности. Вот тут-то у меня и возникла идея написать программу, где будет сразу несколько погодных информеров, чтобы можно было сравнить данные.
Идея положена, теперь нужно найти информацию. На первом же запросе Google выдал мне несколько хороших погодных сервисов со свободными API, я в них успешно зарегистрировался и уже через два часа была готова консольная программа на C# для получения погоды в текстовом виде из WorldWeatherOnline.
 C# я выбрал по одной простой причине - хотелось немного накопить опыта в разработке .NET приложений. К тому же, как оказалось, в нём очень хорошо можно парсить XML данные, которые приходили в ответ на запрос к погодному информеру.



 День второй. Шаг вперёд.

"Случайности не случайны." (Конфуций).
 Текстовые данные это хорошо, но для родителей это будет не так удобно, да и моя душа требовала чего-то намного большего, чем просто консольная версия. Случайно (см. цитату) мне на глаза попался обзор Windows 8, где как раз промелькнул погодный информер. И тут я понял, что это именно то, что я хочу!


 Теперь я визуально мог представить, что хочу видеть в конечном итоге.
 Взглянув на свой вчерашний код, я понял, что неправильно сделал декомпозицию, пришлось всё перепроектировать. Вскоре была готова обновлённая версия консольной программы, где с лёгкостью можно было добавлять новые погодные сервисы. Добавление погоды от Google заняло всего лишь 10 минут.


 День третий. GUI.

 Добавил погоду от Weather Underground и начал рисовать GUI'шку.
 Сперва поставил картинку на фон: this.BackgroundImage = Bitmap.FromFile("bg\\1.jpg");
Затем долгое время придумывал, как разделить рабочую область на части, чтобы везде хватало места для вывода информации. Потом добавил полупрозрачные панельки и быстренько нарисовал в Paint.NET стрелочки переключения погодных сервисов. Получилось вот такое:



 День четвёртый. Current condition.

 Чтобы не загружать информацию из Интернета при каждом отладочном запуске, я создал класс тестового варианта информера, где все данные уже были вбиты. Продолжалось настраивание положений компонент, и к концу дня была готова панель текущего состояния погоды (Current Condition):



День пятый. Прилив сил.

  С самого утра я чувствовал большой заряд бодрости. Быть может это от того, что вчера программировал лишь пол дня, а может из-за того, что просто хорошо выспался. Направив энергию в нужное русло, я сел за компьютер.
  Первым делом сделал показ информации в прозрачных панельках. Затем подключил не тестовый класс погодного информера и получил такую картину:


  От радости, что всё хорошо работает, я за четыре часа сделал вывод логотипа погодного информера, отключение активности стрелки переключения погодника, кэширование изображений и приведение данных из разных источников к одному типу.


  Пару слов хочу сказать о кэшировании. В нём нет ничего сложного, идея не нова, но делается это так.
  Допустим, грузим мы картинки из интернета по какой-то ссылке. Хэшируем ссылку и получаем число (к примеру 917746485). После того, как загрузили из Интернета, сохраняем картинку на диске под этим именем (например 917746485.jpg, но можно и без расширения). В итоге у нас все загруженные картинки сохраняются на диске. Теперь осталось в самом начале метода загрузки добавить проверку наличия файла 917746485.jpg, и если такой существует, то возвращать именно этот файл. В коде это выглядит так:
protected Bitmap downloadImage(string url)
{
    // Получаем полный адрес к предполагаемой картинке из кэша. 
    string imageCasheUrl = Path.Combine(Constants.APP_CASHE_PATH, url.GetHashCode().ToString());
    if (File.Exists(imageCasheUrl))
    {
        // Если файл существует - отдаём его.
        return new Bitmap(imageCasheUrl);
    }
    // Иначе грузим из Интернета.
    Bitmap result = null;
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    HttpWebResponse response = null;
    try
    {
        response = (HttpWebResponse)req.GetResponse();
        Stream stream = response.GetResponseStream();
        result = new Bitmap(stream);
        // Сохраняем загруженную картинку в кэш.
        result.Save(imageCasheUrl, ImageFormat.Png);
        stream.Close();
    }
    catch (Exception ex)
    {
#if DEBUG
                System.Diagnostics.Debug.WriteLine(ex.ToString());
#endif
    }
    finally
    {
        response.Close();
    }
    return result;
}

День шестой. Настройки.

  Изначально я не планировал никаких настроек, просто хотел вбить данные в текстовый конфиг и грузить настройки из файла. Но по странному стечению обстоятельств я решил идти до конца и сделать-таки эти настройки. Полученный вид окна меня совершенно не удовлетворил, так как он не вписывался в Metro-подобный стиль:


Поэтому пришлось делать новый вид окна, чем я и занялся в оставшееся время.


День седьмой. Программный финал.

  Полон решительности, я с самого утра отлаживал программу и писал текст справки. К вечеру всё было собрано воедино и отдано тестеру, также был сделан скриншот программы для показа его народу:


  Исправив все ошибки, которые были найдены тестером, я должен был бы вздохнуть с облегчением, но почему-то этого не происходило. Я должен был сделать что-то еще, и вскоре понял что именно...
  Иконки! Они были просто ужасны. Я делал их на скорую руку в Paint.NET, уделяя на их рисование ничтожно малое время. 
  И тут, как по взмаху волшебной палочки, мне написала одногруппница-дизайнер, которая и подсказала, что нужно исправить и как выглядело бы лучше.


День восьмой. Иконки.

  Приняв во внимание слова опытного дизайнера, я приступил к рисованию иконок. На этот раз я рисовал их в Photoshop'e и уделял им большое количество времени:


Вот теперь моя душа была чиста, можно было смело отправлять программу в паблик!


ScreenWeather

Программу можно скачать отсюда.
Для запуска нужен установленный .NET Framework 2.0 или выше, скачать его можно здесь.
Также необходимо наличие шрифта Segoe WP, его можно скачать на странице загрузки программы.

Комментариев нет:

Отправить комментарий