Опубликован: 22.12.2015 | Уровень: для всех | Доступ: платный
Лекция 9:

Календарь

Разработка интерфейса пользователя

В этом разделе мы поговорим о том, как создать календарь с помощью библиотеки i18n_ucalendar_h.

Создайте новый проект 'CalendarSample'. Откройте файл исходного кода внесите следующие изменения в начале файла.

#include "calendarsample.h"
#include <utils_i18n.h>

typedef struct appdata {
Evas_Object *win;
Evas_Object *conform;
Evas_Object *label;
Evas_Object *label_day[6][7];
char *tzid;
i18n_ucalendar_h ucal;
} appdata_s;

label_day — это метка, предназначенная для отображения даты. В выделенном пространстве будет отображаться 7 столбцов по горизонтали и 6 строк по вертикали.

В переменной tzid будет храниться временная зона.

В переменной ucal будут храниться текущие дата и время.

Добавьте функцию выше create_base_gui(). Эта функция добавит контролы к таблице.

static void
my_table_pack(Evas_Object *table, Evas_Object *child, int x, int y, int w, int h)
{
evas_object_size_hint_align_set(child, 0.5, 0.5);
evas_object_size_hint_weight_set(child, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_table_pack(table, child, x, y, w, h);
evas_object_show(child);
}

Далее, добавьте код в конец функции create_base_gui(). Этот код создает контролы Box и Table, а также добавляет метку Label.

/* Conformant */
/*ad->conform = elm_conformant_add(ad->win);
elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(ad->win, ad->conform);
evas_object_show(ad->conform);*/
/* Box to put the table in so we can bottom-align the table
* window will stretch all resize object content to win size */
Evas_Object *box = elm_box_add(ad->win);
evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(ad->win, box);
evas_object_show(box);
/* Table */
Evas_Object *table = elm_table_add(ad->win);
/* Make table homogenous - every cell will be the same size */
elm_table_homogeneous_set(table, EINA_TRUE);
/* Set padding of 10 pixels multiplied by scale factor of UI */
elm_table_padding_set(table, 10 * elm_config_scale_get(), 10 * elm_config_scale_get());
/* Let the table child allocation area expand within in the box */
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
/* Set table to fiill width but align to bottom of box */
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, 0.0);
elm_box_pack_end(box, table);
evas_object_show(table);
{
/* Label*/
ad->label = elm_label_add(ad->win);
elm_object_text_set(ad->label, "<align=center>Calendar Sample</align>");
my_table_pack(table, ad->label, 0, 0, 7, 1);
for(int j=0; j < 6; j++)
{
for(int i=0; i < 7; i++)
{
ad->label_day[j][i] = elm_label_add(ad->win);
elm_object_text_set(ad->label_day[j][i], ".");
my_table_pack(table, ad->label_day[j][i], i, j + 2, 1, 1);
}
}
}
/* Show window after base gui is set up */
evas_object_show(ad->win);

С помощью двух циклов for, мы создаем метку с 6 столбцами и 7 строками.

Запустите пример. Символ '.' отображает вновь созданные метки.


Отображение текущей даты и времени

В этом разделе мы создадим объект i18n_ucalendar_h и отобразим текущую дату и время на экране. Добавьте две функции выше create_base_gui().

static i18n_ucalendar_h
create_time(char *tzid)
{
i18n_ucalendar_h ucal;
i18n_uchar *_tzid = (i18n_uchar*)calloc(strlen(tzid) + 1, sizeof(i18n_uchar));
i18n_ustring_copy_ua(_tzid, tzid);
int len = i18n_ustring_get_length(_tzid);
int ret = i18n_ucalendar_create(_tzid, len, "en_US", I18N_UCALENDAR_TRADITIONAL, &ucal);
return ucal;
}
static char* time2string(i18n_ucalendar_h ucal)
{
int year, month, day, hour, minute, second;
i18n_ucalendar_get(ucal, I18N_UCALENDAR_YEAR, &year);
i18n_ucalendar_get(ucal, I18N_UCALENDAR_MONTH, &month);
i18n_ucalendar_get(ucal, I18N_UCALENDAR_DATE, &day);
i18n_ucalendar_get(ucal, I18N_UCALENDAR_HOUR, &hour);
i18n_ucalendar_get(ucal, I18N_UCALENDAR_MINUTE, &minute);
i18n_ucalendar_get(ucal, I18N_UCALENDAR_SECOND, &second);
char *buf = malloc(100);
sprintf(buf, "Now :%04d-%02d-%02d %02d:%02d:%02d", year, month + 1, day, hour, minute, second);
return buf;
}

create_time() - это функция, которая создает и затем возвращает объект i18n_ucalendar_h object, а time2string() - это функция, которая превращает дату, сохраненную в объекте i18n_ucalendar_h в строку и возвращает строку. Добавьте код в конце функции create_base_gui().

evas_object_show(ad->win);
system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_TIMEZONE,&ad->tzid);
ad->ucal = create_time(ad->tzid);
char *buf = time2string(ad->ucal);
elm_object_text_set(ad->label, buf);
}

Запрос временной зоны осуществляетс с помощью функции system_settings_get_value_string(). Создайте объект i18n_ucalendar_h с помощью функции create_time(). Преобразуйте дату и время, сохраненные в объекте i18n_ucalendar_h в одиночную строку с помощью функции time2string().

Запустите проект снова. Дата и время отображаются в метке.


Расчет календарных дат

В этом разделе мы поговорим о том, как определить день недели первого дня текущего месяца и ввести дату в массив меток. Создайте функцию выше create_base_gui().

static void
draw_calendar(appdata_s *ad)
{
int date, month, dow, days, is_leap;
int max_day[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
i18n_ucalendar_set(ad->ucal, I18N_UCALENDAR_DATE, 1);
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_MONTH, &month);
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_DAY_OF_WEEK, &dow);
days = max_day[month];
if( month == 1 )
{
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_IS_LEAP_MONTH, &is_leap);
if( is_leap == 1 )
days = 29;
}
int i=0, j=0;
char buf[10];
i = dow - 1;
for(int d=1; d <= days; d++)
{
sprintf(buf, "%d", d);
elm_object_text_set(ad->label_day[ j][i], buf);
i ++;
if( i >= 7 )
{
i = 0;
j ++;
}
}
}

max_day[] - это массив, в котором хранится максимальное количество дней в месяцах с января по декабрь.

i18n_ucalendar_set() - это API, который определяет новые значения для определенного элемента объекта i18n_ucalendar_h.

i18n_ucalendar_get() - это API, который возвращает значение определенного элемента объекта i18n_ucalendar_h.

Если год високосный, то в феврале будет 29 дней.

Добавьте строчку в конце функции create_base_gui().

elm_object_text_set(ad->label, buf);
draw_calendar(ad);
}

Запустите пример. На экране будет отображаться календарь.


Отображение текущей даты

В этом разделе мы реализуем возможность заключения текущей даты в квадратные скобки. Добавьте строчку в функцию draw_calendar().

static void
draw_calendar(appdata_s *ad)
{
int date, month, dow, days, is_leap;
int max_day[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_DATE, &date);
i18n_ucalendar_set(ad->ucal, I18N_UCALENDAR_DATE, 1);
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_MONTH, &month);
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_DAY_OF_WEEK, &dow);
days = max_day[month];
if( month == 1 )
{
i18n_ucalendar_get(ad->ucal, I18N_UCALENDAR_IS_LEAP_MONTH, &is_leap);
if( is_leap == 1 )
days = 29;
}
int i=0, j=0;
char buf[10];
i = dow - 1;
for(int d=1; d <= days; d++)
{
sprintf(buf, "%d", d);
if( d == date )
sprintf(buf, "[%d]", d);
elm_object_text_set(ad->label_day[ j][i], buf);
~

Мы запрашиваем текущую дату с помощью функции i18n_ucalendar_get() и сохраняем ее в переменной.

Запустите пример. Текущая дата заключена в квадратные скобки.