From 90e3235702c541e14e7073557f25810f56a0a36a Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 31 Aug 2018 12:18:52 +0200 Subject: gl: Form filling UI. When clicking a text/choice/signature field, pop up a dialog to fill in the value. Hide widget annotations in annotation editor. --- platform/gl/gl-annotate.c | 25 +++-- platform/gl/gl-app.h | 2 + platform/gl/gl-form.c | 253 +++++++++++++++++++++++++++++++++++++--------- platform/gl/gl-main.c | 42 +------- 4 files changed, 221 insertions(+), 101 deletions(-) diff --git a/platform/gl/gl-annotate.c b/platform/gl/gl-annotate.c index 1cfe4544..48f0555e 100644 --- a/platform/gl/gl-annotate.c +++ b/platform/gl/gl-annotate.c @@ -461,7 +461,8 @@ void do_annotate_panel(void) n = 0; for (annot = pdf_first_annot(ctx, page); annot; annot = pdf_next_annot(ctx, annot)) - ++n; + if (pdf_annot_type(ctx, annot) != PDF_ANNOT_WIDGET) + ++n; ui_list_begin(&annot_list, n, 0, ui.lineheight * 10 + 4); for (annot = pdf_first_annot(ctx, page); annot; annot = pdf_next_annot(ctx, annot)) @@ -469,15 +470,12 @@ void do_annotate_panel(void) char buf[256]; int num = pdf_to_num(ctx, annot->obj); enum pdf_annot_type subtype = pdf_annot_type(ctx, annot); - if (subtype == PDF_ANNOT_WIDGET) + if (subtype != PDF_ANNOT_WIDGET) { - pdf_obj *ft = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(FT)); - fz_snprintf(buf, sizeof buf, "%d: Widget %s", num, pdf_to_name(ctx, ft)); - } - else fz_snprintf(buf, sizeof buf, "%d: %s", num, pdf_string_from_annot_type(ctx, subtype)); - if (ui_list_item(&annot_list, annot->obj, buf, selected_annot == annot)) - selected_annot = annot; + if (ui_list_item(&annot_list, annot->obj, buf, selected_annot == annot)) + selected_annot = annot; + } } ui_list_end(&annot_list); @@ -515,10 +513,7 @@ void do_annotate_panel(void) ui_spacer(); - if (subtype == PDF_ANNOT_WIDGET) - do_widget_panel(); - else - do_annotate_contents(); + do_annotate_contents(); ui_spacer(); @@ -1062,6 +1057,10 @@ void do_annotate_canvas(fz_irect canvas_area) for (annot = pdf_first_annot(ctx, page); annot; annot = pdf_next_annot(ctx, annot)) { + enum pdf_annot_type subtype = pdf_annot_type(ctx, annot); + if (subtype == PDF_ANNOT_WIDGET) + continue; + bounds = pdf_bound_annot(ctx, annot); bounds = fz_transform_rect(bounds, view_page_ctm); area = fz_irect_from_rect(bounds); @@ -1078,7 +1077,7 @@ void do_annotate_canvas(fz_irect canvas_area) if (annot == selected_annot) { - switch (pdf_annot_type(ctx, selected_annot)) + switch (subtype) { default: break; diff --git a/platform/gl/gl-app.h b/platform/gl/gl-app.h index 0faa35b0..cad23617 100644 --- a/platform/gl/gl-app.h +++ b/platform/gl/gl-app.h @@ -238,11 +238,13 @@ extern fz_matrix draw_page_ctm, view_page_ctm, view_page_inv_ctm; extern fz_rect page_bounds, draw_page_bounds, view_page_bounds; extern fz_irect view_page_area; extern char filename[]; +extern int showform; void run_main_loop(void); void do_annotate_panel(void); void do_annotate_canvas(fz_irect canvas_area); void do_widget_panel(void); +void do_widget_canvas(fz_irect canvas_area); void render_page(void); void update_title(void); void reload(void); diff --git a/platform/gl/gl-form.c b/platform/gl/gl-form.c index e09faa16..4e0c4b88 100644 --- a/platform/gl/gl-form.c +++ b/platform/gl/gl-form.c @@ -84,75 +84,230 @@ static void cert_file_dialog(void) } } -void do_widget_panel(void) -{ - int ff, type; - char *value; +static pdf_widget *sig_widget; +static char sig_status[500]; +static int sig_result; - ff = pdf_get_field_flags(ctx, selected_annot->page->doc, selected_annot->obj); - type = pdf_field_type(ctx, selected_annot->page->doc, selected_annot->obj); +static void sig_dialog(void) +{ + const char *label = pdf_field_label(ctx, sig_widget->page->doc, sig_widget->obj); - if (type == PDF_WIDGET_TYPE_TEXT) + ui_dialog_begin(400, ui.gridsize*3 + ui.lineheight*10); { - static pdf_annot *last_annot = NULL; - static struct input input; - ui_label("Value:"); - if (selected_annot != last_annot) + ui_layout(T, X, NW, 2, 2); + + ui_label("%s", label); + ui_spacer(); + + if (sig_result) + ui_label("Signature is valid.\n%s", sig_status); + else + ui_label("Could not verify signature:\n%s", sig_status); + + ui_layout(B, X, NW, 2, 2); + ui_panel_begin(0, ui.gridsize, 0, 0, 0); { - last_annot = selected_annot; - value = pdf_field_value(ctx, selected_annot->page->doc, selected_annot->obj); - ui_input_init(&input, value); - fz_free(ctx, value); + ui_layout(R, NONE, S, 0, 0); + if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE)) + ui.dialog = NULL; + ui_spacer(); + if (ui_button("Sign")) + { + fz_strlcpy(cert_filename, filename, sizeof cert_filename); + ui_init_open_file(".", cert_file_filter); + ui.dialog = cert_file_dialog; + } } - if (ui_input(&input, 0, (ff & PDF_TX_FIELD_IS_MULTILINE) ? 5 : 1) >= UI_INPUT_EDIT) + ui_panel_end(); + } + ui_dialog_end(); +} + +static void show_sig_dialog(pdf_widget *widget) +{ + sig_widget = widget; + sig_result = pdf_check_signature(ctx, pdf, widget, sig_status, sizeof sig_status); + ui.dialog = sig_dialog; +} + +static pdf_widget *tx_widget; +static struct input tx_input; + +static void tx_dialog(void) +{ + int ff = pdf_get_field_flags(ctx, tx_widget->page->doc, tx_widget->obj); + const char *label = pdf_field_label(ctx, tx_widget->page->doc, tx_widget->obj); + int tx_h = (ff & PDF_TX_FIELD_IS_MULTILINE) ? 10 : 1; + int lbl_h = ui_break_lines((char*)label, NULL, 20, 394, NULL); + int is; + + ui_dialog_begin(400, ui.gridsize*3 + ui.lineheight*(tx_h+lbl_h-1)); + { + ui_layout(T, X, NW, 2, 2); + ui_label("%s", label); + is = ui_input(&tx_input, 200, tx_h); + + ui_layout(B, X, NW, 2, 2); + ui_panel_begin(0, ui.gridsize, 0, 0, 0); { - pdf_field_set_value(ctx, selected_annot->page->doc, selected_annot->obj, input.text); - if (pdf_update_page(ctx, selected_annot->page)) - render_page(); + ui_layout(R, NONE, S, 0, 0); + if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE)) + ui.dialog = NULL; + ui_spacer(); + if (ui_button("Okay") || is == UI_INPUT_ACCEPT) + { + pdf_field_set_value(ctx, tx_widget->page->doc, tx_widget->obj, tx_input.text); + if (pdf_update_page(ctx, tx_widget->page)) + render_page(); + ui.dialog = NULL; + } } + ui_panel_end(); } - else if (type == PDF_WIDGET_TYPE_COMBOBOX || type == PDF_WIDGET_TYPE_LISTBOX) + ui_dialog_end(); +} + +void show_tx_dialog(pdf_widget *widget) +{ + char *value; + value = pdf_field_value(ctx, widget->page->doc, widget->obj); + ui_input_init(&tx_input, value); + fz_free(ctx, value); + ui.focus = &tx_input; + ui.dialog = tx_dialog; + tx_widget = widget; +} + +static pdf_widget *ch_widget; +static void ch_dialog(void) +{ + const char *label; + char *value; + const char **options; + int n, choice; + int label_h; + + label = pdf_field_label(ctx, ch_widget->page->doc, ch_widget->obj); + label_h = ui_break_lines((char*)label, NULL, 20, 394, NULL); + n = pdf_choice_widget_options(ctx, ch_widget->page->doc, ch_widget, 0, NULL); + options = fz_malloc_array(ctx, n, sizeof(char*)); + pdf_choice_widget_options(ctx, ch_widget->page->doc, ch_widget, 0, options); + value = pdf_field_value(ctx, ch_widget->page->doc, ch_widget->obj); + + ui_dialog_begin(400, ui.gridsize*3 + ui.lineheight*label_h); { - const char **options; - int n, choice; - ui_label("Value:"); - n = pdf_choice_widget_options(ctx, selected_annot->page->doc, selected_annot, 0, NULL); - options = fz_malloc_array(ctx, n, sizeof(char*)); - pdf_choice_widget_options(ctx, selected_annot->page->doc, selected_annot, 0, options); - value = pdf_field_value(ctx, selected_annot->page->doc, selected_annot->obj); + ui_layout(T, X, NW, 2, 2); + + ui_label("%s", label); choice = ui_select("Widget/Ch", value, options, n); if (choice >= 0) + pdf_field_set_value(ctx, ch_widget->page->doc, ch_widget->obj, options[choice]); + + ui_layout(B, X, NW, 2, 2); + ui_panel_begin(0, ui.gridsize, 0, 0, 0); { - pdf_field_set_value(ctx, selected_annot->page->doc, selected_annot->obj, options[choice]); - if (pdf_update_page(ctx, selected_annot->page)) - render_page(); + ui_layout(R, NONE, S, 0, 0); + if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE)) + ui.dialog = NULL; + ui_spacer(); + if (ui_button("Okay")) + { + if (pdf_update_page(ctx, ch_widget->page)) + render_page(); + ui.dialog = NULL; + } } - fz_free(ctx, value); - fz_free(ctx, options); + ui_panel_end(); } - else if (type == PDF_WIDGET_TYPE_SIGNATURE) + ui_dialog_end(); + + fz_free(ctx, value); + fz_free(ctx, options); +} + +void do_widget_canvas(fz_irect canvas_area) +{ + pdf_ui_event event; + pdf_widget *widget; + fz_rect bounds; + fz_irect area; + fz_point p; + + if (!pdf) + return; + + p = fz_transform_point_xy(ui.x, ui.y, view_page_inv_ctm); + + if (ui.down && !ui.active) { - if (ui_button("Verify")) + event.etype = PDF_EVENT_TYPE_POINTER; + event.event.pointer.pt = p; + event.event.pointer.ptype = PDF_POINTER_DOWN; + if (pdf_pass_event(ctx, pdf, page, &event)) { - char status[100]; - int result; - result = pdf_check_signature(ctx, pdf, selected_annot, status, sizeof status); - if (result) - ui_show_warning_dialog("Signature is valid.\n%s", status); - else - ui_show_warning_dialog("Could not verify signature:\n%s", status); + if (pdf->focus) + ui.active = &do_widget_canvas; + if (pdf_update_page(ctx, page)) + render_page(); } - if (ui_button("Sign")) + } + else if (ui.active == &do_widget_canvas && !ui.down) + { + ui.active = NULL; + event.etype = PDF_EVENT_TYPE_POINTER; + event.event.pointer.pt = p; + event.event.pointer.ptype = PDF_POINTER_UP; + if (pdf_pass_event(ctx, pdf, page, &event)) { - fz_strlcpy(cert_filename, filename, sizeof cert_filename); - ui_init_open_file(".", cert_file_filter); - ui.dialog = cert_file_dialog; + if (pdf_update_page(ctx, page)) + render_page(); } } - else + + for (widget = pdf_first_widget(ctx, pdf, page); widget; widget = pdf_next_widget(ctx, widget)) { - value = pdf_field_value(ctx, pdf, selected_annot->obj); - ui_label("Value: %s", value); - fz_free(ctx, value); + bounds = pdf_bound_widget(ctx, widget); + bounds = fz_transform_rect(bounds, view_page_ctm); + area = fz_irect_from_rect(bounds); + + if (ui_mouse_inside(&canvas_area) && ui_mouse_inside(&area)) + { + ui.hot = widget; + if (!ui.active && ui.down) + ui.active = widget; + } + + if (ui.hot == widget || showform) + { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glColor4f(0, 0, 1, 0.1f); + glRectf(area.x0, area.y0, area.x1, area.y1); + glDisable(GL_BLEND); + } + + if (pdf_get_field_flags(ctx, NULL, widget->obj) & PDF_FIELD_IS_READ_ONLY) + continue; + + if ((ui.hot == widget && ui.active == widget && !ui.down) || + (pdf->focus == widget && !ui.down)) + { + switch (pdf_widget_type(ctx, widget)) + { + case PDF_WIDGET_TYPE_TEXT: + show_tx_dialog(widget); + break; + case PDF_WIDGET_TYPE_LISTBOX: + case PDF_WIDGET_TYPE_COMBOBOX: + ui.dialog = ch_dialog; + ch_widget = widget; + break; + case PDF_WIDGET_TYPE_SIGNATURE: + show_sig_dialog(widget); + break; + } + pdf->focus = NULL; + pdf->focus_obj = NULL; + } } } diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c index 2089ef96..dcb97c21 100644 --- a/platform/gl/gl-main.c +++ b/platform/gl/gl-main.c @@ -129,6 +129,7 @@ static int showlinks = 0; static int showsearch = 0; static int showinfo = 0; static int showhelp = 0; +int showform = 0; struct mark { @@ -547,44 +548,6 @@ static void do_search_hits(void) glDisable(GL_BLEND); } -static void do_forms(void) -{ - static int do_forms_tag = 0; - pdf_ui_event event; - fz_point p; - - if (!pdf || search_active) - return; - - p = fz_transform_point_xy(ui.x, ui.y, view_page_inv_ctm); - - if (ui.down && !ui.active) - { - event.etype = PDF_EVENT_TYPE_POINTER; - event.event.pointer.pt = p; - event.event.pointer.ptype = PDF_POINTER_DOWN; - if (pdf_pass_event(ctx, pdf, (pdf_page*)page, &event)) - { - if (pdf->focus) - ui.active = &do_forms_tag; - if (pdf_update_page(ctx, page)) - render_page(); - } - } - else if (ui.active == &do_forms_tag && !ui.down) - { - ui.active = NULL; - event.etype = PDF_EVENT_TYPE_POINTER; - event.event.pointer.pt = p; - event.event.pointer.ptype = PDF_POINTER_UP; - if (pdf_pass_event(ctx, pdf, (pdf_page*)page, &event)) - { - if (pdf_update_page(ctx, page)) - render_page(); - } - } -} - static void toggle_fullscreen(void) { static int win_x = 0, win_y = 0; @@ -829,6 +792,7 @@ static void do_app(void) case 'a': toggle_annotate(); break; case 'o': toggle_outline(); break; case 'L': showlinks = !showlinks; break; + case 'F': showform = !showform; break; case 'i': showinfo = !showinfo; break; case 'r': reload(); break; case 'q': glutLeaveMainLoop(); break; @@ -1140,7 +1104,7 @@ static void do_canvas(void) } else { - do_forms(); + do_widget_canvas(area); do_links(links); do_page_selection(); } -- cgit v1.2.3