scheduler — u_pbt_scheduler #
← Referência dos componentes · Índice do guia
Um calendário à maneira do Outlook: vistas dia, semana de trabalho, semana, mês e agenda, faixa « dia inteiro », arrastar e largar para mover e redimensionar, recursos lado a lado, categorias de cor, e cartões e tooltips escritos por modelos. Preenche-se compromisso a compromisso, ou numa só chamada a partir de um DataStore — e cada gesto do utilizador devolve a linha a atualizar.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Scheduler: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Userobject | u_pbt_scheduler |
| Classes de items | n_pbt_scheduler_appointment (um compromisso, of_appointment) · n_pbt_scheduler_resource (um recurso, of_resource) · n_pbt_scheduler_category (uma categoria, of_category) |
| Serve para | Planeamento de uma equipa, reserva de salas ou máquinas, agenda de um comercial, consultas de doentes — tudo o que assenta em dias e horas |
| Limite no modo de demonstração | Os 12 primeiros compromissos do intervalo no ecrã, por hora de início; os outros ficam em memória sem serem apresentados — ver o modo de demonstração |
Início rápido #
// open event of the window : a few appointments of the week, in one repaint
uo_sched.of_set_redraw(/*on*/ false)
uo_sched.is_date = "2026-09-21"
// A colour category, then the appointments : a key, a subject, a start and an end
uo_sched.of_add_category(/*key*/ "customer", /*label*/ "Customer", /*color*/ RGB(216, 90, 48))
uo_sched.of_add_appointment(/*key*/ "a1", /*subject*/ "Weekly meeting", /*start*/ "2026-09-21 09:00", /*end*/ "2026-09-21 10:00")
uo_sched.of_appointment(/*key*/ "a1").is_location = "Room 3"
uo_sched.of_add_appointment(/*key*/ "a2", /*subject*/ "ACME visit", /*start*/ "2026-09-23 14:00", /*end*/ "2026-09-23 16:30")
uo_sched.of_appointment(/*key*/ "a2").is_category = "customer"
// Dates only : an all-day appointment, both days included
uo_sched.of_add_appointment(/*key*/ "a3", /*subject*/ "Trade fair", /*start*/ "2026-09-24", /*end*/ "2026-09-25")
uo_sched.of_appointment(/*key*/ "a3").ib_all_day = true
uo_sched.of_set_redraw(/*on*/ true)
// ue_appointment_opened event of uo_sched : (string as_key)
// A double-click, or Enter on the selected appointment : open YOUR editor
wf_edit_appointment(as_key)
Compreender o calendário #
As vistas #
is_view escolhe a vista, is_date o dia à volta do qual ela se constrói: a sua semana, o seu mês. O utilizador muda uma e outro a partir da barra de ferramentas do componente (Hoje, anterior, seguinte, menu das vistas) — as duas propriedades releem-se em direto, e ue_view_changed / ue_date_changed indicam-no, venha a mudança do utilizador ou do seu código.
| Vista | O que mostra |
|---|---|
VIEW_DAY | Um dia numa grelha horária |
VIEW_WORK_WEEK | Os dias úteis da semana (is_work_days) — a vista predefinida |
VIEW_WEEK | Os sete dias, a partir de ii_first_day_of_week |
VIEW_MONTH | Seis semanas; um compromisso de vários dias estende-se como barra sobre os seus dias |
VIEW_AGENDA | Uma lista, dia a dia, sobre ii_agenda_days dias |
As datas #
Uma data viaja como texto, "yyyy-mm-dd hh:mm" — nos métodos, nas propriedades e nos eventos. É uma hora local flutuante: sem fuso horário nem hora de verão; "2026-09-22 09:00" aparece às 09:00, em todos os postos.
- O fim é exclusivo. Um compromisso das 09:00 às 10:00 termina às 10:00: o seguinte, que começa às 10:00, não se sobrepõe. Sem fim, um compromisso dura 30 minutos.
- Uma data sem hora inclui os seus dois dias.
"2026-09-24"→"2026-09-25"comib_all_day = trueé o dia 24 e o dia 25. Para um dia inteiro a hora é ignorada: uma coluna datetime de DataWindow, que traz00:00:00, dá dias, o último incluído. - O que o calendário também aceita:
"2026-09-22T09:30", segundos, e o texto de uma coluna datetime de DataWindow.of_add_appointmenttem uma sobrecarga que recebe doisdatetime. - O que os eventos devolvem: as datas na forma em que as escreveu —
"yyyy-mm-dd hh:mm", fim exclusivo, para um compromisso com hora; apenas datas, ambos os dias incluídos, para um dia inteiro. É também o queis_starteis_endreleem no handle.
// Local variables
datetime ldt_start
// A "yyyy-mm-dd hh:mm" text back into a PowerBuilder datetime
ldt_start = DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12)))
A faixa « dia inteiro » #
Por cima da grelha horária das vistas dia e semana, uma faixa recebe os compromissos ib_all_day e os que duram 24 horas ou mais: um seminário de três dias cabe lá numa barra em vez de esmagar três colunas. ib_all_day_band = false retira-a. Na vista mês, esses compromissos são barras que atravessam os seus dias; os outros, uma linha escrita por is_month_template.
Os compromissos de um DataStore #
of_from_datastore(ids) carrega o calendário numa só chamada: uma linha = um compromisso, e a sua chave é o seu número de linha — é ela que cada evento devolve, pronta para SetItem. Uma coluna desempenha um papel quando tem o seu nome, ou quando of_map lho atribui:
| Papel | Nomes reconhecidos sem of_map |
|---|---|
ROLE_SUBJECT | subject, title |
ROLE_START · ROLE_END | start, start_date, starts · end, end_date, ends |
ROLE_ALL_DAY · ROLE_READ_ONLY | all_day, allday · read_only, readonly |
ROLE_KEY · ROLE_LOCATION · ROLE_ORGANIZER · ROLE_DESCRIPTION · ROLE_RESOURCE · ROLE_CATEGORY · ROLE_STATUS · ROLE_RECURRING · ROLE_PRIVATE · ROLE_REMINDER · ROLE_CANCELLED | o nome do papel: key, location, organizer, description, resource, category, status, recurring, private, reminder, cancelled |
- Uma coluna booleana é verdadeira para
1,true,Youyes. Uma colunastatustem os valores deSTATUS_*(busy,tentative,free,oof,elsewhere). Cada nome é reconhecido também com o prefixois_: is_private, já queprivateé uma palavra reservada do PowerScript. - Todas as colunas, com papel ou não, são campos dos modelos: uma coluna
customerescreve-se{customer}no cartão, e lê-se comof_get_field. - Uma coluna que desempenha
ROLE_KEYsubstitui o número de linha como chave: reserve-a para dados que não recarrega a partir desse DataStore. Os seus valores devem ser únicos e não vazios: uma linha que não o respeita (ou cujo valor contém/ou|) mantém o seu número de linha como chave, eue_script_errorindica-o uma vez. - O calendário nunca modifica o DataStore: diz-lhe o que o utilizador fez (
ue_appointment_moved,ue_appointment_resized), fazSetIteme depoisUpdate()quando a sua aplicação o decidir. - Depois de um
InsertRow,DeleteRow,SortouFilter, os números de linha mudam: volte a chamarof_from_datastore.
Recursos e agrupamento #
Um recurso é aquilo que se reserva: uma pessoa, uma sala, uma máquina (of_add_resource). Um compromisso nomeia-o através de is_resource. Com is_group_by = GROUP_RESOURCE, cada dia das vistas dia e semana divide-se em uma coluna por recurso, e arrastar um cartão para outra coluna muda o seu recurso — ue_appointment_moved devolve-o em as_resource. ib_visible = false num recurso oculta a sua coluna e os seus compromissos, como desmarcar um calendário no Outlook.
Cores, categorias e estado #
A cor de um cartão decide-se por esta ordem: o il_accent definido neste compromisso, depois a cor da sua categoria (of_add_category, is_category), depois a do seu recurso, depois o destaque do tema. O filete à esquerda indica o estado (is_status, o « Mostrar como » do Outlook: ocupado, provisório, livre, ausente, noutro local); um compromisso ib_cancelled é desenhado vazio, e ib_recurring, ib_private, ib_reminder colocam um pequeno sinal no cartão.
Propriedades #
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_view | string | VIEW_WORK_WEEK | A vista apresentada (VIEW_*). Relida em direto: o utilizador muda-a a partir da barra de ferramentas. Defini-la emite ue_view_changed, como o menu das vistas (nada se a vista não mudar) |
is_date | string | hoje | O dia apresentado, "yyyy-mm-dd": a vista constrói-se à sua volta (a sua semana, o seu mês). Relido em direto: as setas deslocam-no. Uma vez definido, is_now já não o desloca; "" devolve a vista a hoje |
is_now | string | "" | « Agora », para a linha da hora atual e o botão Hoje: "" = o relógio do posto; "yyyy-mm-dd hh:mm" fixa-o (demonstração, teste, repetição). Enquanto is_date nunca tiver sido definido, a vista vai ao seu dia |
ii_first_day_of_week | integer | 1 | Primeiro dia da semana, em números ISO como is_work_days: 1 = segunda-feira … 7 = domingo; 0 é aceite para domingo |
is_work_days | string | "1|2|3|4|5" | Os dias úteis, números ISO unidos por | (1 = segunda-feira … 7 = domingo, 0 aceite para domingo): formam a semana de trabalho, os outros ficam sombreados |
is_work_start · is_work_end | string | "08:00" · "17:00" | O horário de trabalho, "hh:mm": o resto do dia fica sombreado |
is_day_start · is_day_end | string | "00:00" · "24:00" | As horas que a grelha horária mostra; o que fica de fora é contado na borda da sua coluna (« ▲ 1 antes », « ▼ 1 depois »), com o que o deslocamento esconde acima ou abaixo da vista; um clique na marca traz à vista o compromisso escondido mais próximo |
ii_slot_minutes | integer | 30 | O passo da grelha em minutos: 5, 10, 15, 20, 30 ou 60. Um arrastar alinha-se por ele |
ii_hour_height | integer | 48 | A altura de uma hora, em píxeis |
is_scroll_time | string | "08:00" | A hora para a qual a grelha se desloca ao abrir uma vista |
ib_show_now | boolean | true | A linha vermelha da hora atual |
ib_toolbar | boolean | true | A barra de ferramentas: Hoje, anterior, seguinte, o título, o menu das vistas |
ib_week_numbers | boolean | false | Os números de semana ISO, no canto da grelha horária e antes de cada linha do mês |
ib_read_only | boolean | false | Nada se move, redimensiona ou cria com o rato; Delete já não pede nada |
ib_all_day_band | boolean | true | A faixa « dia inteiro » por cima da grelha horária |
ib_tooltips | boolean | true | O tooltip de cada compromisso, escrito pelos modelos de tooltip |
ib_veto_changes | boolean | false | Pergunta antes de aplicar uma deslocação ou um redimensionamento: emite ue_appointment_changing, que pode recusar |
is_card_template | string | "[b]{subject}[/b]{?location}; {location}{/location}" | O modelo do cartão: vistas dia e semana, agenda, barras do mês — ver Os modelos |
is_month_template | string | "{!all_day}{start} {/all_day}{subject}" | Uma linha da vista mês, para um compromisso contido num dia |
is_tooltip_title_template | string | "{subject}" | O título do tooltip de um compromisso |
is_tooltip_template | string | a hora, o local, o organizador | O texto do tooltip de um compromisso — ver Os modelos |
is_group_by | string | GROUP_NONE | GROUP_RESOURCE: uma coluna por recurso sob cada dia, mais uma coluna (nenhum) no fim quando um compromisso não tem um recurso conhecido do calendário |
is_filter | string | "" | Mostra apenas os compromissos que contêm este texto (assunto, local, organizador, descrição, campos); "" mostra-os todos |
is_time_format | string | "hh:mm" | Como se escreve uma hora: "hh:mm", "h:mm AM/PM"… (símbolos de Os modelos) |
ii_agenda_days | integer | 7 | Quantos dias a vista agenda lista |
is_theme_style | string | "" | Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança |
is_theme_mode | string | "" | Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema) |
is_tooltip | string | "" | Tooltip simples do componente (um compromisso tem o seu, escrito pelos modelos) |
is_super_tooltip_title | string | "" | Título do tooltip enriquecido (tem prioridade sobre is_tooltip) |
is_super_tooltip_text | string | "" | Texto do tooltip enriquecido (formatação com etiquetas aceite) |
is_super_tooltip_image | string | "" | Imagem do tooltip enriquecido |
Propriedades de um compromisso #
Um compromisso controla-se pelo seu handle, of_appointment("chave") — criado no primeiro acesso, continua válido depois. Uma propriedade lida pergunta ao componente quanto vale agora: depois de um arrastar, is_start e is_end já dizem onde o utilizador o largou.
// A handle used once fits on one line
uo_sched.of_appointment(/*key*/ "a1").is_status = n_pbt_scheduler_appointment.STATUS_TENTATIVE
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_subject | string | o de of_add_appointment | O assunto, o que o cartão mostra primeiro ({subject}) |
is_start · is_end | string | os de of_add_appointment | Início e fim, "yyyy-mm-dd hh:mm", fim exclusivo; para um dia inteiro, datas "yyyy-mm-dd", ambos os dias incluídos. Qualquer outra escrita (22/09/2026 09:00) é guardada mas nunca desenhada |
ib_all_day | boolean | false | Ocupa dias inteiros: desenhado na faixa « dia inteiro » |
is_location · is_organizer · is_description | string | "" | O local ({location}), o organizador ({organizer}), um texto mais longo ({description}) |
is_resource | string | "" | A chave do seu recurso: a sua coluna quando o calendário agrupa por recurso, a sua cor quando não tem categoria |
is_category | string | "" | A chave da sua categoria: a cor do cartão |
is_status | string | STATUS_BUSY | O « Mostrar como » do Outlook (STATUS_*), desenhado pelo filete à esquerda |
ib_recurring · ib_private · ib_reminder | boolean | false | Pequenos sinais no cartão: uma periodicidade, um compromisso privado, um lembrete |
ib_cancelled | boolean | false | Um compromisso cancelado é desenhado vazio |
ib_read_only | boolean | false | O utilizador não o pode mover, redimensionar nem pedir a sua eliminação |
ib_visible | boolean | true | Oculta-o sem o retirar |
Como qualquer item, um compromisso tem também o tooltip comum (is_tooltip, is_super_tooltip_title, is_super_tooltip_text, is_super_tooltip_image) — que então substitui o dos modelos — e as cores de item: il_accent recolore o cartão e o seu filete, il_back_color, il_text_color, il_back_color_hover e il_text_color_hover pintam-no em repouso e ao passar o rato.
Propriedades de um recurso e de uma categoria #
| Propriedade | Handle | Função |
|---|---|---|
is_label | n_pbt_scheduler_resource | O nome apresentado por cima da sua coluna quando o calendário agrupa por recurso ({resource_label}) |
il_color | n_pbt_scheduler_resource | A cor dos seus compromissos sem categoria; -1 = o destaque |
ib_visible | n_pbt_scheduler_resource | false oculta a sua coluna e os seus compromissos |
is_label | n_pbt_scheduler_category | O seu nome ({category_label}) |
il_color | n_pbt_scheduler_category | A cor dos seus compromissos; -1 = o destaque. Uma categoria não é desenhada por si: o tooltip e as cinco cores de item que herda são guardados e relidos, sem efeito visível |
Constantes #
| Família | Constantes | Definidas em |
|---|---|---|
| Vista | VIEW_DAY, VIEW_WORK_WEEK, VIEW_WEEK, VIEW_MONTH, VIEW_AGENDA | o componente (is_view) |
| Agrupamento | GROUP_NONE, GROUP_RESOURCE | o componente (is_group_by) |
| Papel de uma coluna | ROLE_KEY, ROLE_SUBJECT, ROLE_START, ROLE_END, ROLE_ALL_DAY, ROLE_LOCATION, ROLE_ORGANIZER, ROLE_DESCRIPTION, ROLE_RESOURCE, ROLE_CATEGORY, ROLE_STATUS, ROLE_RECURRING, ROLE_PRIVATE, ROLE_REMINDER, ROLE_CANCELLED, ROLE_READ_ONLY | o componente (of_map) |
| Estado | STATUS_BUSY, STATUS_TENTATIVE, STATUS_FREE, STATUS_OOF, STATUS_ELSEWHERE | o handle de compromisso (is_status) |
As constantes leem-se no objeto que as define:
u_pbt_scheduler.VIEW_MONTHpara uma propriedade do componente,n_pbt_scheduler_appointment.STATUS_OOFpara uma propriedade de compromisso.
Métodos #
Compromissos #
| Método | Função | |
|---|---|---|
of_add_appointment (string as_key, string as_subject, string as_start, string as_end) | Acrescenta um compromisso: a sua chave (única), o seu assunto, o seu início e fim "yyyy-mm-dd hh:mm". Tudo o resto passa pelo seu handle. Devolve 0 uma vez acrescentado, -5 quando a chave está vazia, contém / ou ` | , ou **já está ocupada** (um compromisso não se atualiza assim: é o seu handle que o faz), ou quando o início — ou um fim indicado — não está escrito yyyy-mm-dd ou yyyy-mm-dd hh:mm (String(ldt) escreve 22/09/2026 num posto francês: use a sobrecarga datetime), -2` quando o componente não está criado |
of_add_appointment (string as_key, string as_subject, datetime adt_start, datetime adt_end) | O mesmo, a partir de dois datetime; um fim nulo vale o início. Para um dia inteiro, o fim é o próprio último dia, incluído: duas vezes a mesma data = um dia. Devolve 0 uma vez acrescentado, -5 quando a chave está vazia, contém / ou ` | ou já está ocupada, ou quando o início é nulo, -2` quando o componente não está criado |
of_appointment (string as_key) | O handle de um compromisso (n_pbt_scheduler_appointment), criado no primeiro acesso — ver Propriedades de um compromisso | |
of_remove_appointment (string as_key) | Retira um compromisso. Devolve 0 uma vez retirado, -5 quando o calendário não tem nenhum compromisso com esta chave, -2 quando o componente não está criado | |
of_clear_appointments ( ) | Retira todos os compromissos; recursos, categorias e opções ficam. Devolve 0 uma vez enviado, -2 quando o componente não está criado | |
of_set_field (string as_key, string as_field, string as_value) | Dá a um compromisso um campo seu, para os modelos: depois de of_set_field("a1", "customer", "ACME"), {customer} escreve ACME no seu cartão. Devolve 0 uma vez definido, -5 quando o campo está vazio ou o calendário não tem nenhum compromisso com esta chave, -2 quando o componente não está criado | |
of_get_field (string as_key, string as_field) | Lê em direto um campo de um compromisso: um dos seus (of_set_field) ou uma coluna do DataStore de onde veio; "" quando não o tem |
DataStore #
| Método | Função |
|---|---|
of_from_datastore (datastore ads) | A ponte DataStore: uma linha = um compromisso, a sua chave = o seu número de linha, cada coluna = um campo dos modelos. Substitui os compromissos apresentados. Devolve 0 uma vez carregado, -5 quando o DataStore não é válido ou não tem nenhuma coluna, -2 quando o componente não está criado |
of_map (string as_role, string as_column) | Dá um papel (ROLE_*) a uma coluna cujo nome não o diz: of_map(ROLE_SUBJECT, "title_text"). Antes ou depois de of_from_datastore: depois, cada linha é relida tal como está agora — um compromisso retirado continua retirado, um arrastado fica onde foi largado, os campos de of_set_field e os compromissos acrescentados à mão ficam. Devolve 0 uma vez definido, -5 quando o papel não é uma das constantes ROLE_* ou quando a coluna não é uma das do DataStore do último of_from_datastore; um novo ROLE_KEY dá a cada linha uma nova chave, e os handles das antigas são libertados, -2 quando o componente não está criado |
Recursos e categorias #
| Método | Função | |
|---|---|---|
of_add_resource (string as_key, string as_label) | Acrescenta um recurso — uma pessoa, uma sala, uma máquina; a sua cor e a sua visibilidade passam por of_resource. Devolve 0 uma vez acrescentado, -5 quando a chave está vazia, contém / ou ` | , ou já está ocupada, -2` quando o componente não está criado |
of_resource (string as_key) | O handle de um recurso (n_pbt_scheduler_resource), criado no primeiro acesso | |
of_remove_resource (string as_key) | Retira um recurso; os seus compromissos ficam — agrupados por recurso, na coluna (nenhum). Devolve 0 uma vez retirado, -5 quando o calendário não tem nenhum recurso com esta chave, -2 quando o componente não está criado | |
of_clear_resources ( ) | Retira todos os recursos. Devolve 0 uma vez enviado, -2 quando o componente não está criado | |
of_add_category (string as_key, string as_label, long al_color) | Acrescenta uma categoria de cor: os compromissos cujo is_category a nomeia tomam a sua cor (-1 = o destaque). Devolve 0 uma vez acrescentada, -5 quando a chave está vazia, contém / ou ` | , ou já está ocupada, -2` quando o componente não está criado |
of_category (string as_key) | O handle de uma categoria (n_pbt_scheduler_category), criado no primeiro acesso | |
of_remove_category (string as_key) | Retira uma categoria; os seus compromissos voltam ao destaque. Devolve 0 uma vez retirada, -5 quando o calendário não tem nenhuma categoria com esta chave, -2 quando o componente não está criado | |
of_clear_categories ( ) | Retira todas as categorias. Devolve 0 uma vez enviado, -2 quando o componente não está criado |
Navegação e seleção #
| Método | Função |
|---|---|
of_next ( ) | O dia, a semana ou o mês seguinte — a seta da barra de ferramentas. Devolve 0 uma vez enviado, -2 quando o componente não está criado |
of_previous ( ) | O dia, a semana ou o mês anterior. Devolve 0 uma vez enviado, -2 quando o componente não está criado |
of_go_to_today ( ) | Volta a hoje — o botão Hoje. Devolve 0 uma vez enviado, -2 quando o componente não está criado |
of_select_appointment (string as_key) | Seleciona um compromisso ("" = nenhum), como um clique: emite ue_selection_changed (nada se já for a seleção). Devolve 0 uma vez selecionado, -5 quando o calendário não tem nenhum compromisso com esta chave, -2 quando o componente não está criado |
of_selected_key ( ) | A chave do compromisso selecionado, "" quando nenhum — lida em direto |
of_show_appointment (string as_key) | Traz um compromisso para a vista: vai ao seu dia, desloca-se até à sua hora e seleciona-o, como um clique: emite ue_selection_changed. Um dia que a semana de trabalho não mostra (um sábado) passa a vista para a semana inteira, e ue_view_changed indica-o. Devolve 0 uma vez mostrado, -5 quando o calendário não tem nenhum compromisso com esta chave, -2 quando o componente não está criado |
of_scroll_to_time (string as_time) | Desloca a grelha horária até uma hora, "hh:mm". Devolve 0 uma vez enviado, -5 quando a hora está vazia, -2 quando o componente não está criado |
of_first_visible_date ( ) · of_last_visible_date ( ) | O primeiro e o último dia que a vista mostra, "yyyy-mm-dd" — lidos em direto |
of_shown_count ( ) | Devolve o número de compromissos apresentados no intervalo no ecrã: depois de is_filter, dos ocultos, dos recursos ocultos e do limite do modo de demonstração (os 12 primeiros desse intervalo); of_count conta todo o calendário |
Eventos #
| Evento | Emitido quando |
|---|---|
ue_appointment_clicked (string as_key) | Um compromisso foi clicado (e selecionado) |
ue_appointment_opened (string as_key) | Duplo clique num compromisso, ou Enter no selecionado: abra o seu editor |
ue_appointment_rclicked (string as_key, long al_x, long al_y) | Clique direito num compromisso. al_x / al_y são píxeis de ecrã |
ue_appointment_changing (string as_key, string as_start, string as_end, string as_resource) | Antes de uma deslocação ou redimensionamento ser aplicado, só se ib_veto_changes for verdadeiro. Devolva false para repor o compromisso onde estava; true por predefinição |
ue_appointment_moved (string as_key, string as_start, string as_end, string as_resource) | O utilizador arrastou um compromisso: o seu novo início, o seu novo fim e o seu recurso. O calendário já o mostra lá; grave-o (uma linha de DataStore: SetItem na linha Long(as_key)) |
ue_appointment_resized (string as_key, string as_start, string as_end) | O utilizador arrastou uma extremidade de um compromisso: o seu novo início e fim |
ue_range_selected (string as_start, string as_end, boolean ab_all_day, string as_resource) | O utilizador percorreu casas vazias com o rato: o intervalo, para criar nele um compromisso. Percorrido na faixa « dia inteiro » ou na vista mês, são dias inteiros: ab_all_day vale true, só datas, a última incluída |
ue_new_requested (string as_start, string as_end, boolean ab_all_day, string as_resource) | O utilizador pede um novo compromisso: duplo clique numa casa ou num dia vazio, ou o + de um cabeçalho de dia (agrupado por recurso: de um cabeçalho de recurso). Um dia inteiro chega só com datas, o fim incluído: duas vezes a mesma data = um dia |
ue_delete_requested (string as_key) | Delete foi premida no compromisso selecionado. Retire-o (of_remove_appointment) quando a sua aplicação concordar |
ue_slot_rclicked (string as_start, boolean ab_all_day, string as_resource, long al_x, long al_y) | Clique direito numa casa ou num dia vazio; para um dia, as_start é só a sua data. al_x / al_y são píxeis de ecrã |
ue_selection_changed (string as_key) | O compromisso selecionado mudou ("" = nenhum): um clique, ou of_select_appointment / of_show_appointment a partir do seu código |
ue_view_changed (string as_view) | A vista mudou: o utilizador escolheu outra na barra de ferramentas ou abriu um dia pelo seu « +N », o seu código definiu is_view, ou of_show_appointment passou a semana de trabalho para a semana inteira para mostrar um dia de folga |
ue_date_changed (string as_first, string as_last) | O intervalo visível mudou (navegação, vista, data): o seu primeiro e último dia, "yyyy-mm-dd", incluídos. Emitido também na primeira apresentação (sobre o intervalo de hoje), e de novo quando o seu código define is_date ou is_view: uma janela que os define ao abrir recebe dois; e depois de cada of_reset, que esvazia o calendário: é um pedido de dados, não um gesto. É aqui que se carregam os compromissos do intervalo |
ue_ready ( ) | O componente terminou de carregar; tudo o que foi enviado antes foi reproduzido |
ue_runtime_missing ( ) | O runtime WebView2 está ausente: o componente fica vazio |
ue_bg_color (long al_color) | O componente calculou a sua cor de fundo do tema; o userobject já a adotou (backcolor) |
Os modelos #
O que um cartão, uma linha do mês e um tooltip dizem não é fixo: é um modelo que escreve, em texto formatado ([b], [br], [color=…], [symbol=…]…) com campos entre chavetas. Quatro propriedades os definem: is_card_template (cartões das vistas dia e semana, agenda, barras do mês), is_month_template (uma linha da vista mês), is_tooltip_title_template e is_tooltip_template (o tooltip). O modelo de tooltip predefinido é:
[symbol=clock] {when}{?location}[br][symbol=location] {location}{/location}{?organizer}[br][symbol=person] {organizer}{/organizer}
A sintaxe #
| Escrita | Efeito |
|---|---|
{subject} | O valor do campo, escapado: um [ no assunto aparece, não abre uma etiqueta |
{start:dddd d mmmm} | Um campo de data num formato (símbolos abaixo) |
{?location}…{/location} | Escreve o bloco só se o campo disser algo que não seja um NÃO: nem vazio, nem 0, N, no ou false |
{!all_day}…{/all_day} | Escreve o bloco só se o campo estiver vazio (ou falso) |
{description:raw} | Insere o valor como formatação, sem o escapar — para um campo que já contém etiquetas |
{{ · }} | Uma chaveta literal |
Os formatos de data #
Os símbolos são os do PowerBuilder; os nomes dos dias e dos meses seguem a língua de apresentação. Um texto entre aspas é escrito tal como está. Os mesmos símbolos servem para is_time_format.
| Símbolo | Escreve |
|---|---|
yyyy · yy | O ano, 2026 · 26 |
mmmm · mmm | O nome do mês, longo · curto |
mm · m | O mês, 09 · 9 — ou os minutos logo a seguir a uma hora, como no PowerBuilder |
dddd · ddd | O nome do dia, longo · curto |
dd · d | O dia do mês, 05 · 5 |
hh · h | A hora, 09 · 9 (em 12 horas com AM/PM) |
nn · n | Os minutos, 05 · 5 |
AM/PM · am/pm | O indicador da manhã ou da tarde |
Os campos #
| Campo | Valor |
|---|---|
key · subject · location · organizer · description | A chave e os textos do compromisso |
resource · resource_label | A chave do seu recurso · o seu nome |
category · category_label | A chave da sua categoria · o seu nome |
status · status_label | O estado (busy…) · o seu rótulo, traduzido na língua de apresentação |
all_day · recurring · private · reminder · cancelled | true, ou vazio: feitos para {?…} e {!…} |
start · end | A hora de início · de fim, no formato is_time_format (vazia para um dia inteiro); com um formato, a data e a hora — para um dia inteiro, {end:…} é o último dia, como is_end o relê |
date | O primeiro dia, por extenso; com um formato, o início formatado |
time | 09:00-10:30, ou « Todo o dia » |
when | A frase completa: dia, horas, e o dia de fim quando difere |
duration | 45 min, 1 h 30, 2 days (traduzido) |
| os seus | Qualquer campo definido por of_set_field, e qualquer coluna do DataStore de of_from_datastore, com o seu nome. Um valor que é uma data aceita um formato: {due_date:dd/mm} |
Um campo desconhecido escreve uma cadeia vazia.
Os símbolos #
A etiqueta de texto formatado [symbol=nome] coloca um símbolo integrado, monocromático, desenhado na cor do texto que o rodeia — segue o tema, a passagem do rato e a cor do cartão, sem ficheiro a distribuir: clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Um nome desconhecido aparece tal como está.
O que o utilizador pode fazer sem uma linha de código #
- navegar: Hoje, anterior, seguinte, e o menu das vistas da barra de ferramentas;
- mover um compromisso para outra hora, outro dia ou outro recurso, arrastando-o — o passo segue
ii_slot_minutes; - redimensionar um compromisso arrastando a sua extremidade;
- percorrer casas vazias para escolher um intervalo →
ue_range_selected— na faixa « dia inteiro » ou na vista mês, dias inteiros; - pedir um compromisso com um duplo clique numa casa vazia ou com o + de um cabeçalho de dia (de um cabeçalho de recurso quando o calendário está agrupado) →
ue_new_requested; - abrir um compromisso com um duplo clique →
ue_appointment_opened, e clicar com o botão direito num compromisso ou numa casa vazia para o seu menu.
O calendário não cria, não modifica nem elimina nada por si além do arrastar: pergunta, a sua aplicação decide. ib_read_only desliga todos estes gestos de uma vez, ib_read_only num compromisso desliga-os só para ele.
Com o teclado, depois de o calendário ter o foco:
| Tecla | Efeito |
|---|---|
| Enter | Abre o compromisso selecionado → ue_appointment_opened |
| Delete | Pede a eliminação do compromisso selecionado → ue_delete_requested (nada se o calendário ou o compromisso estiver só de leitura) |
| Seta acima / Seta abaixo | Seleciona o compromisso anterior / seguinte da vista, pela ordem da hora de início → ue_selection_changed |
| Page Up / Page Down | O dia, a semana ou o mês anterior / seguinte |
| Alt+Home | Volta a hoje |
| Esc | Cancela um arrastar em curso |
Exemplos #
Os compromissos de um DataStore, e o que o utilizador faz com eles #
O DataStore ids_appts (variável de instância) tem as colunas subject, start_date, end_date, location, room, category e customer. As quatro primeiras desempenham o seu papel pelo nome; room recebe-o de of_map.
// open event of the window : the appointments, retrieved the way your application already does
ids_appts = create datastore
ids_appts.dataobject = "d_appointments"
ids_appts.SetTransObject(SQLCA)
ids_appts.Retrieve()
// "room" is not a role name : say which role it plays, then load every row
uo_sched.of_map(/*role*/ u_pbt_scheduler.ROLE_RESOURCE, /*column*/ "room")
uo_sched.of_from_datastore(/*ads*/ ids_appts)
// ue_appointment_moved event of uo_sched : (string as_key, string as_start, string as_end, string as_resource)
// Local variables
long ll_row
// The key of a row loaded by of_from_datastore is its row number
ll_row = Long(as_key)
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.SetItem(ll_row, "room", as_resource)
// Save when YOUR application decides : here, at once
ids_appts.Update()
// ue_appointment_resized event of uo_sched : (string as_key, string as_start, string as_end)
// Local variables
long ll_row
// Only the times change : same row, same two columns
ll_row = Long(as_key)
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.Update()
Criar e eliminar #
// ue_new_requested event of uo_sched : (string as_start, string as_end, boolean ab_all_day, string as_resource)
// Local variables
long ll_row
// A new row, prefilled with the slot the user chose
ll_row = ids_appts.InsertRow(0)
ids_appts.SetItem(ll_row, "subject", "New appointment")
ids_appts.SetItem(ll_row, "start_date", DateTime(Date(Left(as_start, 10)), Time(Mid(as_start, 12))))
ids_appts.SetItem(ll_row, "end_date", DateTime(Date(Left(as_end, 10)), Time(Mid(as_end, 12))))
ids_appts.SetItem(ll_row, "room", as_resource)
// Reload (the row numbers are the keys), then bring the new one into view
uo_sched.of_from_datastore(/*ads*/ ids_appts)
uo_sched.of_show_appointment(/*key*/ String(ll_row))
// ue_delete_requested event of uo_sched : (string as_key)
// Ask first : the calendar never deletes by itself
if MessageBox("Delete", "Delete this appointment?", Question!, YesNo!) = 2 then return
ids_appts.DeleteRow(Long(as_key))
ids_appts.Update()
// The rows after it changed number : reload
uo_sched.of_from_datastore(/*ads*/ ids_appts)
Uma coluna por sala #
// The rooms, each with its own colour, side by side under each day
uo_sched.of_set_redraw(/*on*/ false)
uo_sched.of_add_resource(/*key*/ "r1", /*label*/ "Room A")
uo_sched.of_add_resource(/*key*/ "r2", /*label*/ "Room B")
uo_sched.of_resource(/*key*/ "r1").il_color = RGB(15, 108, 189)
uo_sched.of_resource(/*key*/ "r2").il_color = RGB(31, 158, 117)
uo_sched.is_group_by = u_pbt_scheduler.GROUP_RESOURCE
uo_sched.is_view = u_pbt_scheduler.VIEW_DAY
// Each appointment names its room
uo_sched.of_add_appointment(/*key*/ "k1", /*subject*/ "Kickoff", /*start*/ "2026-09-22 09:00", /*end*/ "2026-09-22 10:00")
uo_sched.of_appointment(/*key*/ "k1").is_resource = "r1"
uo_sched.of_add_appointment(/*key*/ "k2", /*subject*/ "Interview", /*start*/ "2026-09-22 10:30", /*end*/ "2026-09-22 11:30")
uo_sched.of_appointment(/*key*/ "k2").is_resource = "r2"
uo_sched.of_set_redraw(/*on*/ true)
// A checkbox of the window hides Room B and its appointments, like unticking a calendar in Outlook
uo_sched.of_resource(/*key*/ "r2").ib_visible = cbx_room_b.checked
Cartões e tooltips seus #
// The card : the time, the subject in bold, the customer (a DataStore column) when there is one
uo_sched.is_card_template = "{start} [b]{subject}[/b]{?customer}[br][symbol=people] {customer}{/customer}"
// The month line : a small lock on the private ones
uo_sched.is_month_template = "{?private}[symbol=lock] {/private}{subject}"
// The tooltip : the date written out, the duration, the status
uo_sched.is_tooltip_title_template = "{subject}"
uo_sched.is_tooltip_template = "[symbol=calendar] {start:dddd d mmmm}, {time} ({duration})[br][symbol=info] {status_label}"
Recusar uma deslocação #
// Ask before any move or resize is applied
uo_sched.ib_veto_changes = true
// ue_appointment_changing event of uo_sched : (string as_key, string as_start, string as_end, string as_resource) returns boolean
// Nothing on a Saturday or a Sunday : returning false puts the appointment back
if DayNumber(Date(Left(as_start, 10))) = 1 or DayNumber(Date(Left(as_start, 10))) = 7 then return false
return true
Carregar só o que se vê #
Com anos de histórico, não vale a pena ler tudo: ue_date_changed dá o intervalo no ecrã a cada navegação, e na primeira apresentação. Aqui d_appointments recebe dois argumentos datetime, início e fim do intervalo.
// ue_date_changed event of uo_sched : (string as_first, string as_last)
// The last day is INCLUDED : read up to the start of the day after
ids_appts.Retrieve(DateTime(Date(as_first)), DateTime(RelativeDate(Date(as_last), 1)))
uo_sched.of_from_datastore(/*ads*/ ids_appts)
O seu menu num compromisso #
// ue_appointment_rclicked event of uo_sched : (string as_key, long al_x, long al_y)
// Local variables
m_appointment lm_menu
// Remember which appointment the menu is about, then open YOUR menu under the pointer
is_menu_key = as_key
lm_menu = create m_appointment
lm_menu.m_popup.PopMenu(parent.PointerX(), parent.PointerY())
destroy lm_menu
Boas práticas #
- Enquadre uma série de adições com
of_set_redraw(/*on*/ false)/of_set_redraw(/*on*/ true): os compromissos aparecem de uma só vez. - Para dados que vivem numa base, prefira
of_from_datastorea um ciclo deof_add_appointment: uma só transferência, e cada evento devolve a linha. - Recarregue (
of_from_datastore) depois de qualquerInsertRow,DeleteRow,SortouFilterdo DataStore: a chave de um compromisso é um número de linha. - Escreva as datas como
"yyyy-mm-dd hh:mm", nunca no formato regional do posto: é o único que o calendário lê em todo o lado. - Num modelo, envolva um campo facultativo em
{?campo}…{/campo}: um cartão sem local não mostra um « ; » órfão. - Com um histórico longo, carregue o intervalo visível em
ue_date_changedem vez de todo o DataStore. - Para uma regra de negócio (nenhum compromisso ao fim de semana, nenhuma sobreposição numa sala),
ib_veto_changeseue_appointment_changingrecusam antes de o cartão se mover.
Limites da 4.0 #
O que o calendário não faz — convém sabê-lo antes de o escolher:
- Periodicidade: nem séries (regras RRULE), nem exceções, nem edição « esta ocorrência / toda a série ».
ib_recurringsó põe um sinal no cartão: cada ocorrência é um compromisso (uma linha do DataStore) que a sua aplicação gera ela própria. Um motor de periodicidade está previsto para uma versão seguinte. - Fusos horários: a hora é local flutuante (ver As datas); nenhuma segunda escala horária, nenhuma conversão.
- Vista cronológica (recursos em linhas, tempo em colunas) e minicalendário de navegação: ausentes; agrupe por recurso (
GROUP_RESOURCE) nas vistas dia e semana. - iCalendar: nem importação nem exportação de ficheiros
.ics. - Impressão: nenhuma; o calendário desenha-se só no ecrã.
- Teclado: seleciona-se, abre-se, elimina-se e navega-se pelo teclado, mas não se cria nem se move um compromisso sem o rato.
- Data e hora em duas colunas: um início escrito em duas colunas do DataStore não se mapeia; junte-o numa coluna
datetimena consulta.
Herdado da base comum #
Estes membros existem em todos os componentes visuais — não são próprios deste. São detalhados uma só vez, nos capítulos transversais; esta tabela apenas diz onde os ler.
| Membros | Função | Detalhado em |
|---|---|---|
of_count · of_keys_at · of_has | Percorrer o que o componente contém | 3.2 Os items |
of_reset | Repor o componente a zero | 3.6 Repor um componente a zero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atalhos de teclado do componente | 3.5 Os atalhos de teclado |
of_is_created · of_is_ready · of_get_last_error | Se nasceu, se está pronto, o que falhou | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar a renderização como imagem | 3.8 Exportar a representação como imagem |
of_set_redraw | Agrupar as alterações num único repinte | 3.10 Boas práticas |
of_preload_icons | Ícones mostrados sem atraso | Apresentação instantânea: of_icon |
of_set_translation | Traduzir uma legenda do componente | 5.2 Adaptar uma etiqueta: of_set_translation |
of_focus_webview | Dar o foco ao componente | 6.4 Teclado e focus |
of_print · of_print_to_pdf | Imprimir, ou escrever um PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar uma propriedade pelo nome | 3.1 O motor de propriedades |
Duas ajudas não são herdadas: of_icon e of_escape_markup vivem em n_pbt_utils. Declare um — n_pbt_utils lnv_utils, nada a criar — e chame-as nele.