diff --git a/core/org.eclipse.cdt.ui/.classpath b/core/org.eclipse.cdt.ui/.classpath new file mode 100644 index 00000000000..0473ac5fdc3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/.classpath @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/.cvsignore b/core/org.eclipse.cdt.ui/.cvsignore new file mode 100644 index 00000000000..ba077a4031a --- /dev/null +++ b/core/org.eclipse.cdt.ui/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/core/org.eclipse.cdt.ui/.project b/core/org.eclipse.cdt.ui/.project new file mode 100644 index 00000000000..04403a7b87c --- /dev/null +++ b/core/org.eclipse.cdt.ui/.project @@ -0,0 +1,29 @@ + + + org.eclipse.cdt.ui + + + org.eclipse.cdt.core + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/core/org.eclipse.cdt.ui/build.properties b/core/org.eclipse.cdt.ui/build.properties new file mode 100644 index 00000000000..c7f095579a4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/build.properties @@ -0,0 +1,8 @@ +############################################### +# +# (c) Copyright QNX Software Systems Ltd. 2002. +# All Rights Reserved. +# +############################################### + +source.cdtui.jar = src diff --git a/core/org.eclipse.cdt.ui/build.xml b/core/org.eclipse.cdt.ui/build.xml new file mode 100644 index 00000000000..78db196b3ae --- /dev/null +++ b/core/org.eclipse.cdt.ui/build.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/icons/full/clcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.ui/icons/full/clcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..6d772441d0d Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/clcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/clcl16/clear_co.gif b/core/org.eclipse.cdt.ui/icons/full/clcl16/clear_co.gif new file mode 100644 index 00000000000..255832653fd Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/clcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/clcl16/open_incl.gif b/core/org.eclipse.cdt.ui/icons/full/clcl16/open_incl.gif new file mode 100644 index 00000000000..58b9a012e89 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/clcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_l_edit.gif b/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_l_edit.gif new file mode 100644 index 00000000000..2700d541ecf Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_r_edit.gif b/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_r_edit.gif new file mode 100644 index 00000000000..fed137329e7 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/clcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_app.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_app.gif new file mode 100644 index 00000000000..6c2d75db2e6 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_app.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_lib.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_lib.gif new file mode 100644 index 00000000000..c2f865be4db Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newc_lib.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_app.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_app.gif new file mode 100644 index 00000000000..86d78df150f Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_app.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_lib.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_lib.gif new file mode 100644 index 00000000000..aeb778d5b57 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcc_lib.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newcprj_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcprj_wiz.gif new file mode 100644 index 00000000000..812cf458709 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newfile_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newfile_wiz.gif new file mode 100644 index 00000000000..6baa03787f4 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/newfolder_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/newfolder_wiz.gif new file mode 100644 index 00000000000..2b49c1b36aa Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/newfolder_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/next_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/next_error_nav.gif new file mode 100644 index 00000000000..775842e89d1 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/next_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/prev_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/prev_error_nav.gif new file mode 100644 index 00000000000..3b1bb7ca128 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/prev_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/prj_obj.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/prj_obj.gif new file mode 100644 index 00000000000..6624c902a16 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/prj_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ctool16/prop_edt.gif b/core/org.eclipse.cdt.ui/icons/full/ctool16/prop_edt.gif new file mode 100644 index 00000000000..9d5a508bc49 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ctool16/prop_edt.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/cview16/buildconsole.gif b/core/org.eclipse.cdt.ui/icons/full/cview16/buildconsole.gif new file mode 100644 index 00000000000..4723724a209 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/cview16/buildconsole.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/cview16/c_pers.gif b/core/org.eclipse.cdt.ui/icons/full/cview16/c_pers.gif new file mode 100644 index 00000000000..86316d592ee Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/cview16/c_pers.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/cview16/cview.gif b/core/org.eclipse.cdt.ui/icons/full/cview16/cview.gif new file mode 100644 index 00000000000..2a76756b1f1 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/cview16/cview.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dlcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.ui/icons/full/dlcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..62a8fdb555b Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dlcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dlcl16/clear_co.gif b/core/org.eclipse.cdt.ui/icons/full/dlcl16/clear_co.gif new file mode 100644 index 00000000000..d873c49b8a0 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dlcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dlcl16/open_incl.gif b/core/org.eclipse.cdt.ui/icons/full/dlcl16/open_incl.gif new file mode 100644 index 00000000000..9bdd658229f Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dlcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_l_edit.gif b/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_l_edit.gif new file mode 100644 index 00000000000..a93966ed990 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_r_edit.gif b/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_r_edit.gif new file mode 100644 index 00000000000..c1254afc730 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dlcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dtool16/newcprj_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/dtool16/newcprj_wiz.gif new file mode 100644 index 00000000000..82450711805 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dtool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dtool16/newfile_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/dtool16/newfile_wiz.gif new file mode 100644 index 00000000000..c931715bb32 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dtool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dtool16/next_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/dtool16/next_error_nav.gif new file mode 100644 index 00000000000..874bf69d422 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dtool16/next_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/dtool16/prev_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/dtool16/prev_error_nav.gif new file mode 100644 index 00000000000..4c323769b99 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/dtool16/prev_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/elcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.ui/icons/full/elcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..9d38f6dff8a Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/elcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/elcl16/clear_co.gif b/core/org.eclipse.cdt.ui/icons/full/elcl16/clear_co.gif new file mode 100644 index 00000000000..6faf8d66fef Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/elcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/elcl16/open_incl.gif b/core/org.eclipse.cdt.ui/icons/full/elcl16/open_incl.gif new file mode 100644 index 00000000000..aec95f8fbcc Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/elcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_l_edit.gif b/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_l_edit.gif new file mode 100644 index 00000000000..fe7b3111b11 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_r_edit.gif b/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_r_edit.gif new file mode 100644 index 00000000000..e0f2a56933d Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/elcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/etool16/newcprj_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/etool16/newcprj_wiz.gif new file mode 100644 index 00000000000..5f7c6a973f8 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/etool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/etool16/newfile_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/etool16/newfile_wiz.gif new file mode 100644 index 00000000000..f2fe6e1d036 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/etool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/etool16/next_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/etool16/next_error_nav.gif new file mode 100644 index 00000000000..6a8e019b5ad Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/etool16/next_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/etool16/prev_error_nav.gif b/core/org.eclipse.cdt.ui/icons/full/etool16/prev_error_nav.gif new file mode 100644 index 00000000000..2cba4b14ae6 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/etool16/prev_error_nav.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/eview16/buildconsole.gif b/core/org.eclipse.cdt.ui/icons/full/eview16/buildconsole.gif new file mode 100644 index 00000000000..56d14e449eb Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/eview16/buildconsole.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/eview16/c_pers.gif b/core/org.eclipse.cdt.ui/icons/full/eview16/c_pers.gif new file mode 100644 index 00000000000..655cd2f4c21 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/eview16/c_pers.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/ar_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/ar_obj.gif new file mode 100644 index 00000000000..f6064b678ef Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/ar_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/bin_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/bin_obj.gif new file mode 100644 index 00000000000..b96495c7bb1 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/bin_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint.gif new file mode 100644 index 00000000000..4f92c1bf2c7 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_active.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_active.gif new file mode 100644 index 00000000000..5f17a268dec Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_active.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_disabled.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_disabled.gif new file mode 100644 index 00000000000..f6fd492d944 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/breakpoint_disabled.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/build_menu.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/build_menu.gif new file mode 100644 index 00000000000..3fc40d6a13a Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/build_menu.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/c_file_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/c_file_obj.gif new file mode 100644 index 00000000000..1bb68c2d649 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/c_file_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/cdeclaration_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/cdeclaration_obj.gif new file mode 100644 index 00000000000..d079ebb14fa Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/cdeclaration_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/cfolder_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/cfolder_obj.gif new file mode 100644 index 00000000000..33ce8827e17 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/cfolder_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/class_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/class_obj.gif new file mode 100644 index 00000000000..a4a14864987 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/class_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/container_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/container_obj.gif new file mode 100644 index 00000000000..3aa2efae2e0 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/container_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/define_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/define_obj.gif new file mode 100644 index 00000000000..b3ddb5deebc Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/define_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/exec_dbg_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/exec_dbg_obj.gif new file mode 100644 index 00000000000..3052a80cd67 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/exec_dbg_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/exec_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/exec_obj.gif new file mode 100644 index 00000000000..8174dade2bb Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/exec_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/field_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/field_obj.gif new file mode 100644 index 00000000000..19d27defb62 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/field_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/function_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/function_obj.gif new file mode 100644 index 00000000000..18103b11fc7 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/function_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/include_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/include_obj.gif new file mode 100644 index 00000000000..2cc5866a64c Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/include_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/lib_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/lib_obj.gif new file mode 100644 index 00000000000..f966fc39d9b Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/lib_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/shlib_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/shlib_obj.gif new file mode 100644 index 00000000000..4e51447b23b Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/shlib_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/struct_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/struct_obj.gif new file mode 100644 index 00000000000..cb2869f2488 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/struct_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/template_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/template_obj.gif new file mode 100644 index 00000000000..b4d8ea83502 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/template_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/obj16/union_obj.gif b/core/org.eclipse.cdt.ui/icons/full/obj16/union_obj.gif new file mode 100644 index 00000000000..b8405d54bb4 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/obj16/union_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ovr16/c_ovr.gif b/core/org.eclipse.cdt.ui/icons/full/ovr16/c_ovr.gif new file mode 100644 index 00000000000..bec7ac2faef Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ovr16/c_ovr.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ovr16/error_co.gif b/core/org.eclipse.cdt.ui/icons/full/ovr16/error_co.gif new file mode 100644 index 00000000000..8612eaff599 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ovr16/error_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ovr16/static_co.gif b/core/org.eclipse.cdt.ui/icons/full/ovr16/static_co.gif new file mode 100644 index 00000000000..08438a590ab Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ovr16/static_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ovr16/volatile_co.gif b/core/org.eclipse.cdt.ui/icons/full/ovr16/volatile_co.gif new file mode 100644 index 00000000000..8ddf0be719c Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ovr16/volatile_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/ovr16/warning_co.gif b/core/org.eclipse.cdt.ui/icons/full/ovr16/warning_co.gif new file mode 100644 index 00000000000..3af228ceac3 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/ovr16/warning_co.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/wizban/c_app_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/wizban/c_app_wiz.gif new file mode 100644 index 00000000000..60ccf9c7c6a Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/wizban/c_app_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/wizban/newcprj_wiz.gif b/core/org.eclipse.cdt.ui/icons/full/wizban/newcprj_wiz.gif new file mode 100644 index 00000000000..60ccf9c7c6a Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/wizban/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.ui/icons/full/wizban/prj_obj.gif b/core/org.eclipse.cdt.ui/icons/full/wizban/prj_obj.gif new file mode 100644 index 00000000000..6624c902a16 Binary files /dev/null and b/core/org.eclipse.cdt.ui/icons/full/wizban/prj_obj.gif differ diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties new file mode 100644 index 00000000000..de70dea7e70 --- /dev/null +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -0,0 +1,87 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +pluginName=C Development Tools UI + +elementFiltersName=CElement Filters +textHoversName=Text Hovers +editorActionsName=Editor Actions +editorRulerActionsName=Editor Ruler Actions +completionContributorName=Completion Contribution +nature.name=C Nature +perspective.name=C +viewsCategory.name=&C +BuildConsoleView.name=C-Build +CView.name=C/C++ Projects +MakeView.name=Make Targets + +# The Wizard +# C +newCWizardsCategory.name=C +StdCWizard.name =Standard Make C Project +StdCWizard.description=Create a C Project + +# C++ +newCCWizardsCategory.name=C++ +StdCCWizard.name =Standard Make C++ Project +StdCCWizard.description=Create a C++ Project + +NewFileWizard.name=File +NewFileCreationWizard.description=Create a file +OpenNewFileWizardAction.label=&File +OpenNewFileWizardAction.tooltip=Create a File + +NewFolderWizard.name=Folder +NewFolderCreationWizard.description=Create a folder +OpenNewFolderWizardAction.label=&Folder +OpenNewFolderWizardAction.tooltip=Create a Folder + +CEditor.name=C Editor +CPluginPreferencePage.name=C/C++ +CPluginEditorPreferencePage.name=C/C++ Editor +CPluginTemplatePreferencePage.name=Code Templates +CProjectPropertyPage.name=C/C++ Project +CLaunchingPropertyPage.executionArguments.name=C Execution Arguments +CApplicationLauncher.label=Executable +CApplicationLauncher.description=Launch a local command +CProblemMarker.name=C Problem + +CFolderActionSet.label=C Folder Actions +CFolderActionSet.description=C Folder Action Set + +Editors.DefaultTextEditor = Default Text Editor + +#VCM +CompareWithMenu.label=Comp&are With + +CompareWithEachOtherAction.label=&Each Other +CompareWithEachOtherAction.tooltip=Compare the Selected Resources with Each Other + +CompareWithHistoryAction.label= &Local History... +CompareWithHistoryAction.tooltip= Compare the Selected Resource with Local History + +ReplaceWithMenu.label=Rep&lace With + +ReplaceFromHistoryAction.label=&Local History... +ReplaceFromHistoryAction.tooltip=Replace the Selected Resource with Local History + +Editors.DefaultTextEditor = Default Text Editor + +#VCM +CompareWithMenu.label=Comp&are With + +CompareWithEachOtherAction.label=&Each Other +CompareWithEachOtherAction.tooltip=Compare the Selected Resources with Each Other + +CompareWithHistoryAction.label= &Local History... +CompareWithHistoryAction.tooltip= Compare the Selected Resource with Local History + +ReplaceWithMenu.label=Rep&lace With + +ReplaceFromHistoryAction.label=&Local History... +ReplaceFromHistoryAction.tooltip=Replace the Selected Resource with Local History + +# Task Action +DeleteTaskAction.label=Delete C/C++ Markers diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml new file mode 100644 index 00000000000..069301d4764 --- /dev/null +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %StdCWizard.description + + + + + + + + %StdCCWizard.description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/core/DocumentInputStream.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/core/DocumentInputStream.java new file mode 100644 index 00000000000..cadd14d459c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/core/DocumentInputStream.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.internal.core; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + /** + * Input stream which reads from a document + */ +public class DocumentInputStream extends InputStream { + + private IDocument fDocument; + private int fCurrPos; + + public DocumentInputStream(IDocument document) { + fDocument= document; + fCurrPos= 0; + } + + public IDocument getDocument() { + return fDocument; + } + + /** + * @see InputStream#read + */ + public int read() throws IOException { + try { + if (fCurrPos < fDocument.getLength()) { + return fDocument.getChar(fCurrPos++); + } + } catch (BadLocationException e) { + } + return -1; + } + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextType.java new file mode 100644 index 00000000000..92d9145e30b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextType.java @@ -0,0 +1,167 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.textmanipulation.MultiTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.NopTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.SimpleTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.TextBuffer; +import org.eclipse.cdt.internal.corext.textmanipulation.TextBufferEditor; +import org.eclipse.cdt.internal.corext.textmanipulation.TextEdit; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import java.util.Vector; +import org.eclipse.core.runtime.CoreException; + + +/** + * A context type is a context factory. + */ +public abstract class ContextType implements ITemplateEditor { + + /** name of the context type */ + private final String fName; + + /** variables used by this content type */ + private final Map fVariables= new HashMap(); + + /** + * Creates a context type with a name. + * + * @param name the name of the context. It has to be unique wrt to other context names. + */ + public ContextType(String name) { + fName= name; + } + + /** + * Returns the name of the context type. + */ + public String getName() { + return fName; + } + + /** + * Adds a template variable to the context type. + */ + public void addVariable(TemplateVariable variable) { + fVariables.put(variable.getName(), variable); + } + + /** + * Removes a template variable from the context type. + */ + public void removeVariable(TemplateVariable variable) { + fVariables.remove(variable.getName()); + } + + /** + * Removes all template variables from the context type. + */ + public void removeAllVariables() { + fVariables.clear(); + } + + /** + * Returns an iterator for the variables known to the context type. + */ + public Iterator variableIterator() { + return fVariables.values().iterator(); + } + + /** + * Creates a template context. + */ + public abstract TemplateContext createContext(); + + /* + * @see ITemplateEditor#edit(TemplateBuffer) + */ + public void edit(TemplateBuffer templateBuffer, TemplateContext context) throws CoreException { + TextBuffer textBuffer= TextBuffer.create(templateBuffer.getString()); + TemplatePosition[] variables= templateBuffer.getVariables(); + + MultiTextEdit positions= variablesToPositions(variables); + MultiTextEdit multiEdit= new MultiTextEdit(); + + // iterate over all variables and try to resolve them + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + if (variable.isResolved()) + continue; + + String name= variable.getName(); + int[] offsets= variable.getOffsets(); + int length= variable.getLength(); + + TemplateVariable evaluator= (TemplateVariable) fVariables.get(name); + String value= (evaluator == null) + ? null + : evaluator.evaluate(context); + + if (value == null) + continue; + + variable.setLength(value.length()); + variable.setResolved(evaluator.isResolved(context)); + + for (int k= 0; k != offsets.length; k++) + multiEdit.add(SimpleTextEdit.createReplace(offsets[k], length, value)); + } + + TextBufferEditor editor= new TextBufferEditor(textBuffer); + editor.add(positions); + editor.add(multiEdit); + editor.performEdits(null); + + positionsToVariables(positions, variables); + + templateBuffer.setContent(textBuffer.getContent(), variables); + } + + private static MultiTextEdit variablesToPositions(TemplatePosition[] variables) { + MultiTextEdit positions= new MultiTextEdit(); + for (int i= 0; i != variables.length; i++) { + int[] offsets= variables[i].getOffsets(); + for (int j= 0; j != offsets.length; j++) + positions.add(new NopTextEdit(offsets[j], 0)); + } + + return positions; + } + + private static void positionsToVariables(MultiTextEdit positions, TemplatePosition[] variables) { + Iterator iterator= positions.iterator(); + + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + int[] offsets= new int[variable.getOffsets().length]; + for (int j= 0; j != offsets.length; j++) + offsets[j]= ((TextEdit) iterator.next()).getTextRange().getOffset(); + + variable.setOffsets(offsets); + } + } + + /** + * Returns the templates associated with this context type. + */ + public Template[] getTemplates() { + Template[] templates= Templates.getInstance().getTemplates(); + + Vector vector= new Vector(); + for (int i= 0; i != templates.length; i++) + if (templates[i].getContextTypeName().equals(fName)) + vector.add(templates[i]); + + return (Template[]) vector.toArray(new Template[vector.size()]); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextTypeRegistry.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextTypeRegistry.java new file mode 100644 index 00000000000..0a209137921 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ContextTypeRegistry.java @@ -0,0 +1,69 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.c.CContextType; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + + +/** + * A singleton to keep track of all known context types. + */ +public class ContextTypeRegistry { + + /** the singleton */ + private static ContextTypeRegistry fInstance; + + /** all known context types */ + private final Map fContextTypes= new HashMap(); + + /** + * Returns the single instance of this class. + */ + public static ContextTypeRegistry getInstance() { + if (fInstance == null) + fInstance= new ContextTypeRegistry(); + + return fInstance; + } + + /** + * Adds a context type to the registry. + */ + public void add(ContextType contextType) { + fContextTypes.put(contextType.getName(), contextType); + } + + /** + * Removes a context type from the registry. + */ + public void remove(ContextType contextType) { + fContextTypes.remove(contextType.getName()); + } + + /** + * Returns the context type if the name is valid, null otherwise. + */ + public ContextType getContextType(String name) { + return (ContextType) fContextTypes.get(name); + } + + /** + * Returns an iterator over the registered context type names. + */ + public Iterator iterator() { + return fContextTypes.keySet().iterator(); + } + + // XXX bootstrap with C and C++ types + private ContextTypeRegistry() { + add(new CContextType()); + //add(new CppContextType()); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/DocumentTemplateContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/DocumentTemplateContext.java new file mode 100644 index 00000000000..c7a5fcb59bb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/DocumentTemplateContext.java @@ -0,0 +1,70 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.util.Assert; + + + +/** + * A typical text based document template context. + */ +public abstract class DocumentTemplateContext extends TemplateContext { + + /** The text of the document. */ + private final String fString; + /** The completion position. */ + private final int fCompletionPosition; + + /** + * Creates a document template context. + */ + protected DocumentTemplateContext(ContextType type, String string, int completionPosition) { + super(type); + + Assert.isNotNull(string); + Assert.isTrue(completionPosition >= 0 && completionPosition <= string.length()); + + fString= string; + fCompletionPosition= completionPosition; + } + + /** + * Returns the string of the context. + */ + public String getString() { + return fString; + } + + /** + * Returns the completion position within the string of the context. + */ + public int getCompletionPosition() { + return fCompletionPosition; + } + + /** + * Returns the keyword which triggered template insertion. + */ + public String getKey() { + return fString.substring(getStart(), getEnd()); + } + + /** + * Returns the beginning offset of the keyword. + */ + public int getStart() { + return fCompletionPosition; + } + + /** + * Returns the end offset of the keyword. + */ + public int getEnd() { + return fCompletionPosition; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ITemplateEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ITemplateEditor.java new file mode 100644 index 00000000000..dfc057d6f9b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/ITemplateEditor.java @@ -0,0 +1,24 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; + +/** + * A template editor implements an action to edit a template buffer in its context. + */ +public interface ITemplateEditor { + + /** + * Modifies a template buffer. + * + * @param buffer the template buffer + * @param context the template context + * @throws CoreException if the buffer cannot be successfully modified + */ + void edit(TemplateBuffer buffer, TemplateContext context) throws CoreException; + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/SimpleTemplateVariable.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/SimpleTemplateVariable.java new file mode 100644 index 00000000000..2e0ec456df2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/SimpleTemplateVariable.java @@ -0,0 +1,55 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A simple template variable, which always evaluates to a defined string. + */ +public class SimpleTemplateVariable extends TemplateVariable { + + /** The string to which this variable evaluates. */ + private String fEvaluationString; + /** A flag indicating if this variable can be resolved. */ + private boolean fResolved; + + /* + * @see TemplateVariable#TemplateVariable(String, String) + */ + protected SimpleTemplateVariable(String name, String description) { + super(name, description); + } + + /** + * Sets the string to which this variable evaluates. + * + * @param evaluationString the evaluation string, may be null. + */ + public final void setEvaluationString(String evaluationString) { + fEvaluationString= evaluationString; + } + + /* + * @see TemplateVariable#evaluate(TemplateContext) + */ + public String evaluate(TemplateContext context) { + return fEvaluationString; + } + + /** + * Sets the resolved flag. + */ + public final void setResolved(boolean resolved) { + fResolved= resolved; + } + + /* + * @see TemplateVariable#isResolved(TemplateContext) + */ + public boolean isResolved(TemplateContext context) { + return fResolved; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Template.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Template.java new file mode 100644 index 00000000000..f44fcd0c456 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Template.java @@ -0,0 +1,160 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A template consiting of a name and a pattern. + */ +public class Template { + + /** The name of this template */ + private String fName; + /** A description of this template */ + private String fDescription; + /** The name of the context type of this template */ + private String fContextTypeName; + /** The template pattern. */ + private String fPattern; + /** A flag indicating if the template is active or not. */ + private boolean fEnabled= true; + + /** + * Creates an empty template. + */ + public Template() { + this("", "", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + /** + * Creates a copy of a template. + */ + public Template(Template template) { + this(template.getName(), template.getDescription(), template.getContextTypeName(), template.getPattern()); + } + + /** + * Creates a template. + * + * @param name the name of the template. + * @param description the description of the template. + * @param contextTypeName the name of the context type in which the template can be applied. + * @param pattern the template pattern. + */ + public Template(String name, String description, String contextTypeName, String pattern) { + fName= name; + fDescription= description; + fContextTypeName= contextTypeName; + fPattern= pattern; + } + + /* + * @see Object#equals(Object) + */ + public boolean equals(Object object) { + if (!(object instanceof Template)) + return false; + + Template template= (Template) object; + + if (template == this) + return true; + + return + template.fName.equals(fName) && + template.fPattern.equals(fPattern) && + template.fContextTypeName.equals(fContextTypeName); + } + + /* + * @see Object#hashCode() + */ + public int hashCode() { + return fName.hashCode() ^ fPattern.hashCode() ^ fContextTypeName.hashCode(); + } + + /** + * Sets the description of the template. + */ + public void setDescription(String description) { + fDescription= description; + } + + /** + * Returns the description of the template. + */ + public String getDescription() { + return fDescription; + } + + /** + * Sets the name of the context type in which the template can be applied. + */ + public void setContext(String contextTypeName) { + fContextTypeName= contextTypeName; + } + + /** + * Returns the name of the context type in which the template can be applied. + */ + public String getContextTypeName() { + return fContextTypeName; + } + + /** + * Sets the name of the template. + */ + public void setName(String name) { + fName= name; + } + + /** + * Returns the name of the template. + */ + public String getName() { + return fName; + } + + /** + * Sets the pattern of the template. + */ + public void setPattern(String pattern) { + fPattern= pattern; + } + + /** + * Returns the template pattern. + */ + public String getPattern() { + return fPattern; + } + + /** + * Sets the enable state of the template. + */ + public void setEnabled(boolean enable) { + fEnabled= enable; + } + + /** + * Returns true if template is enabled, false otherwise. + */ + public boolean isEnabled() { + return fEnabled; + } + + /** + * Returns true if template matches the prefix and context, + * false otherwise. + */ + public boolean matches(String prefix, String contextTypeName) { + return + fEnabled && + fContextTypeName.equals(contextTypeName) && + (prefix.length() != 0) && + fName.toLowerCase().startsWith(prefix.toLowerCase()); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateBuffer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateBuffer.java new file mode 100644 index 00000000000..1012037c6bc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateBuffer.java @@ -0,0 +1,64 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.util.Assert; + + +/** + * A template buffer is a container for a string and variables. + */ +public final class TemplateBuffer { + + /** The string of the template buffer */ + private String fString; + /** The variable positions of the template buffer */ + private TemplatePosition[] fVariables; + + /** + * Creates a template buffer. + * + * @param string the string + * @param variables the variable positions + * @throws CoreException for illegal variable positions + */ + public TemplateBuffer(String string, TemplatePosition[] variables) throws CoreException { + setContent(string, variables); + } + + /** + * Sets the content of the template buffer. + * + * @param string the string + * @param variables the variable positions + * @throws CoreException for illegal variable positions + */ + public final void setContent(String string, TemplatePosition[] variables) throws CoreException { + Assert.isNotNull(string); + Assert.isNotNull(variables); + + // XXX assert non-overlapping variable properties + + fString= string; + fVariables= variables; + } + + /** + * Returns the string of the template buffer. + */ + public final String getString() { + return fString; + } + + /** + * Returns the variable positions of the template buffer. + */ + public final TemplatePosition[] getVariables() { + return fVariables; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateContext.java new file mode 100644 index 00000000000..56272046f2b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateContext.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; + +/** + * A template context. A template context is associated with a context type. + */ +public abstract class TemplateContext { + + /** context type of this context */ + private final ContextType fContextType; + + /** + * Creates a template context of a particular context type. + */ + protected TemplateContext(ContextType contextType) { + fContextType= contextType; + } + + /** + * Returns the context type of this context. + */ + public ContextType getContextType() { + return fContextType; + } + + /** + * Evaluates the template and returns a template buffer. + */ + public abstract TemplateBuffer evaluate(Template template) throws CoreException; + + /** + * Tests if the specified template can be evaluated in this context. + */ + public abstract boolean canEvaluate(Template template); + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.java new file mode 100644 index 00000000000..a484961b86f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.java @@ -0,0 +1,44 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TemplateMessages { + + private static final String RESOURCE_BUNDLE= TemplateMessages.class.getName(); + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private TemplateMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + */ + public static String getFormattedString(String key, Object arg) { + return MessageFormat.format(getString(key), new Object[] { arg }); + } + + + /** + * Gets a string from the resource bundle and formats it with arguments + */ + public static String getFormattedString(String key, Object[] args) { + return MessageFormat.format(getString(key), args); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.properties new file mode 100644 index 00000000000..73743c48aea --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateMessages.properties @@ -0,0 +1,106 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +# preference page +TemplatePreferencePage.error.import=Failed to import templates. +TemplatePreferencePage.error.export=Failed to export templates. +TemplatePreferencePage.error.read.title=Reading Templates +TemplatePreferencePage.error.write.title=Reading Templates +TemplatePreferencePage.message=&Create, edit or remove templates: +TemplatePreferencePage.title=Templates + +TemplatePreferencePage.new=&New... +TemplatePreferencePage.edit=&Edit... +TemplatePreferencePage.import=&Import... +TemplatePreferencePage.export=E&xport... +TemplatePreferencePage.export.all=Ex&port All... +TemplatePreferencePage.remove=&Remove +TemplatePreferencePage.enable.all=Ena&ble All +TemplatePreferencePage.disable.all=Di&sable All +TemplatePreferencePage.editor=Template + +TemplatePreferencePage.column.name=Name +TemplatePreferencePage.column.context=Context +TemplatePreferencePage.column.description=Description + +TemplatePreferencePage.use.code.formatter=Use Code &Formatter + +TemplatePreferencePage.import.title=Importing Templates +TemplatePreferencePage.import.extension=*.xml + +TemplatePreferencePage.export.title=Exporting {0} Templates +TemplatePreferencePage.export.filename=templates.xml +TemplatePreferencePage.export.extension=*.xml + +TemplatePreferencePage.export.exists.title=Exporting Templates +TemplatePreferencePage.export.message={0} already exists.\nDo you want to replace it? + +TemplatePreferencePage.question.create.new.title=Edit Template +TemplatePreferencePage.question.create.new.message=The name of the template was changed.\nDo you want to create a new template? + +# edit template dialog +EditTemplateDialog.error.noname=Template name must not be empty. +EditTemplateDialog.error.adjacent.variables=Template pattern has adjacent variables. +EditTemplateDialog.title.new=New Template +EditTemplateDialog.title.edit=Edit Template + +EditTemplateDialog.name=&Name: +EditTemplateDialog.description=&Description: +EditTemplateDialog.context=&Context: +EditTemplateDialog.pattern=&Pattern: +EditTemplateDialog.insert.variable=Insert &Variable... + +EditTemplateDialog.undo=&Undo@Ctrl+Z +EditTemplateDialog.cut=Cu&t@Ctrl+X +EditTemplateDialog.copy=&Copy@Ctrl+C +EditTemplateDialog.paste=&Paste@Ctrl+V +EditTemplateDialog.select.all=Select &All@Ctrl+A +EditTemplateDialog.content.assist=Insert &Variable...@Ctrl+Space + +# template variable dialog +TemplateVariableDialog.title=Select a template variable. +TemplateVariableDialog.column.name=Name +TemplateVariableDialog.column.description=Description +TemplateVariableDialog.insert=&Insert + +TemplateVariableProposal.error.title=Error applying template variable proposal +TemplateVariableProcessor.error.title=Error creating template variable proposals + +# template set +TemplateSet.error.read=Error occured while reading templates. +TemplateSet.error.write=Error occured while writing templates. + +# templates +Templates.error.title=Error accessing templates. +Templates.error.read=Error occured while reading templates. +Templates.error.write=Error occured while writing templates. + +# template engine +TemplateEngine.error.title=Could not create template proposals. + +# template proposal +TemplateProposal.delimiter=\ - + +# template evaluator +TemplateEvaluator.error.title=Template Evaluation Error + +# template collector +TemplateCollector.variable.description.file=Filename of compilation unit +TemplateCollector.variable.description.line=Current line number +TemplateCollector.variable.description.date=Current date +TemplateCollector.variable.description.time=Current time +TemplateCollector.variable.description.user=User name +TemplateCollector.variable.description.array=A proposal for an array +TemplateCollector.variable.description.array.type=A proposal for the element type of an array +TemplateCollector.variable.description.array.element=A proposal for the element name of an array +TemplateCollector.variable.description.index=A proposal for an index (int) +TemplateCollector.variable.description.collector=A proposal for a collector (java.util.Collector) +TemplateCollector.variable.description.iterator=A proposal for an iterator (java.util.Iterator) +TemplateCollector.variable.description.return.type=Return type (evaluates to void) +TemplateCollector.variable.description.arguments=Method arguments (evaluates to empty string) + +# template translator +TemplateTranslator.error.incomplete.variable=Template has incomplete variables. +TemplateTranslator.error.invalid.identifier=Template has invalid variable identifiers. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplatePosition.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplatePosition.java new file mode 100644 index 00000000000..e760c48f518 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplatePosition.java @@ -0,0 +1,97 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * + */ +public class TemplatePosition { + + /** The name of the template position */ + private final String fName; + /** The default value of the template position */ + private final String fDefaultValue; + + /** The length of the template positions. */ + private int fLength; + /** The offsets of the template positions. */ + private int[] fOffsets; + /** A flag indicating if the template position has been resolved. */ + private boolean fResolved; + + /** + * Creates a template position. + * + * @param name the name of the template position. + * @param defaultValue the default value of the position. + * @param offsets the array of offsets of the position. + * @param the length of the position. + */ + public TemplatePosition(String name, String defaultValue, int[] offsets, int length) { + fName= name; + fDefaultValue= defaultValue; + fOffsets= offsets; + fLength= length; + fResolved= false; + } + + /** + * Returns the name of the position. + */ + public String getName() { + return fName; + } + + /** + * Returns the default value of the position. + */ + public String getDefaultValue() { + return fDefaultValue; + } + + /** + * Sets the length of the position. + */ + public void setLength(int length) { + fLength= length; + } + + /** + * Returns the length of the position. + */ + public int getLength() { + return fLength; + } + + /** + * Sets the offsets of the position. + */ + public void setOffsets(int[] offsets) { + fOffsets= offsets; + } + + /** + * Returns the offsets of the position. + */ + public int[] getOffsets() { + return fOffsets; + } + + /** + * Sets the resolved flag of the position. + */ + public void setResolved(boolean resolved) { + fResolved= resolved; + } + + /** + * Returns true if the position is resolved, false otherwise. + */ + public boolean isResolved() { + return fResolved; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateSet.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateSet.java new file mode 100644 index 00000000000..94fbff31f63 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateSet.java @@ -0,0 +1,295 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CStatusConstants; +import org.eclipse.cdt.internal.ui.CUIException; +import org.eclipse.cdt.internal.ui.CUIStatus; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.Serializer; +import org.apache.xml.serialize.SerializerFactory; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * TemplateSet manages a collection of templates and makes them + * persistent. + */ +public class TemplateSet { + + private static class TemplateComparator implements Comparator { + public int compare(Object arg0, Object arg1) { + if (arg0 == arg1) + return 0; + + if (arg0 == null) + return -1; + + Template template0= (Template) arg0; + Template template1= (Template) arg1; + + return template0.getName().compareTo(template1.getName()); + } + } + + private static final String TEMPLATE_TAG= "template"; //$NON-NLS-1$ + private static final String NAME_ATTRIBUTE= "name"; //$NON-NLS-1$ + private static final String DESCRIPTION_ATTRIBUTE= "description"; //$NON-NLS-1$ + private static final String CONTEXT_ATTRIBUTE= "context"; //$NON-NLS-1$ + private static final String ENABLED_ATTRIBUTE= "enabled"; //$NON-NLS-1$ + + private List fTemplates= new ArrayList(); + private Comparator fTemplateComparator= new TemplateComparator(); + private Template[] fSortedTemplates= new Template[0]; + + /** + * Convenience method for reading templates from a file. + * + * @see addFromStream(InputStream) + */ + public void addFromFile(File file) throws CoreException { + InputStream stream= null; + + try { + stream= new FileInputStream(file); + addFromStream(stream); + + } catch (IOException e) { + throwReadException(e); + + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException e) {} + } + } + + /** + * Reads templates from a XML stream and adds them to the template set. + */ + public void addFromStream(InputStream stream) throws CoreException { + try { + DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance(); + DocumentBuilder parser= factory.newDocumentBuilder(); + Document document= parser.parse(new InputSource(stream)); + NodeList elements= document.getElementsByTagName(TEMPLATE_TAG); + + int count= elements.getLength(); + for (int i= 0; i != count; i++) { + Node node= elements.item(i); + NamedNodeMap attributes= node.getAttributes(); + + if (attributes == null) + continue; + + String name= getAttributeValue(attributes, NAME_ATTRIBUTE); + String description= getAttributeValue(attributes, DESCRIPTION_ATTRIBUTE); + String context= getAttributeValue(attributes, CONTEXT_ATTRIBUTE); + Node enabledNode= attributes.getNamedItem(ENABLED_ATTRIBUTE); + + if (name == null || description == null || context == null) + throw new SAXException("Missing required attribute"); + + boolean enabled= (enabledNode == null) || (enabledNode.getNodeValue().equals("true")); //$NON-NLS-1$ + + StringBuffer buffer= new StringBuffer(); + NodeList children= node.getChildNodes(); + for (int j= 0; j != children.getLength(); j++) { + String value= children.item(j).getNodeValue(); + if (value != null) + buffer.append(value); + } + String pattern= buffer.toString().trim(); + + Template template= new Template(name, description, context, pattern); + template.setEnabled(enabled); + add(template); + } + + sort(); + + } catch (ParserConfigurationException e) { + throwReadException(e); + } catch (IOException e) { + throwReadException(e); + } catch (SAXException e) { + throwReadException(e); + } + } + + private String getAttributeValue(NamedNodeMap attributes, String name) { + Node node= attributes.getNamedItem(name); + + return node == null + ? null + : node.getNodeValue(); + } + + /** + * Convenience method for saving to a file. + * + * @see saveToStream(OutputStream) + */ + public void saveToFile(File file) throws CoreException { + OutputStream stream= null; + + try { + stream= new FileOutputStream(file); + saveToStream(stream); + + } catch (IOException e) { + throwWriteException(e); + + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException e) {} + } + } + + /** + * Saves the template set as XML. + */ + public void saveToStream(OutputStream stream) throws CoreException { + try { + DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance(); + DocumentBuilder builder= factory.newDocumentBuilder(); + Document document= builder.newDocument(); + + Node root= document.createElement("templates"); // $NON-NLS-1$ //$NON-NLS-1$ + document.appendChild(root); + + for (int i= 0; i != fTemplates.size(); i++) { + Template template= (Template) fTemplates.get(i); + + Node node= document.createElement("template"); // $NON-NLS-1$ //$NON-NLS-1$ + root.appendChild(node); + + NamedNodeMap attributes= node.getAttributes(); + + Attr name= document.createAttribute(NAME_ATTRIBUTE); + name.setValue(template.getName()); + attributes.setNamedItem(name); + + Attr description= document.createAttribute(DESCRIPTION_ATTRIBUTE); + description.setValue(template.getDescription()); + attributes.setNamedItem(description); + + Attr context= document.createAttribute(CONTEXT_ATTRIBUTE); + context.setValue(template.getContextTypeName()); + attributes.setNamedItem(context); + + Attr enabled= document.createAttribute(ENABLED_ATTRIBUTE); + enabled.setValue(template.isEnabled() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ + attributes.setNamedItem(enabled); + + Text pattern= document.createTextNode(template.getPattern()); + node.appendChild(pattern); + } + + OutputFormat format = new OutputFormat(); + format.setPreserveSpace(true); + Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format); //$NON-NLS-1$ + serializer.asDOMSerializer().serialize(document); + + } catch (ParserConfigurationException e) { + throwWriteException(e); + } catch (IOException e) { + throwWriteException(e); + } + } + + private static void throwReadException(Throwable t) throws CoreException { + IStatus status= new CUIStatus(CStatusConstants.TEMPLATE_IO_EXCEPTION, + TemplateMessages.getString("TemplateSet.error.read"), t); //$NON-NLS-1$ + throw new CUIException(status); + } + + private static void throwWriteException(Throwable t) throws CoreException { + IStatus status= new CUIStatus(CStatusConstants.TEMPLATE_IO_EXCEPTION, + TemplateMessages.getString("TemplateSet.error.write"), t); //$NON-NLS-1$ + throw new CUIException(status); + } + + /** + * Adds a template to the set. + */ + public void add(Template template) { + if (exists(template)) + return; // ignore duplicate + + fTemplates.add(template); + sort(); + } + + private boolean exists(Template template) { + for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) { + Template anotherTemplate = (Template) iterator.next(); + + if (template.equals(anotherTemplate)) + return true; + } + + return false; + } + + /** + * Removes a template to the set. + */ + public void remove(Template template) { + fTemplates.remove(template); + sort(); + } + + /** + * Empties the set. + */ + public void clear() { + fTemplates.clear(); + sort(); + } + + /** + * Returns all templates. + */ + public Template[] getTemplates() { + return (Template[]) fTemplates.toArray(new Template[fTemplates.size()]); + } + + private void sort() { + fSortedTemplates= (Template[]) fTemplates.toArray(new Template[fTemplates.size()]); + Arrays.sort(fSortedTemplates, fTemplateComparator); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateTranslator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateTranslator.java new file mode 100644 index 00000000000..1159f94ecdc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateTranslator.java @@ -0,0 +1,215 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.core.runtime.CoreException; + +/** + * The template translator translates a string into a template buffer. + * The EBNF grammer of a valid string is as follows: + * + *

+ * template := (text | escape)*.
+ * text := character - dollar.
+ * escape := dollar ('{' identifier '}' | dollar).
+ * dollar := '$'.
+ *

+ */ +public class TemplateTranslator { + + // states + private static final int TEXT= 0; + private static final int ESCAPE= 1; + private static final int IDENTIFIER= 2; + + // tokens + private static final char ESCAPE_CHARACTER= '$'; + private static final char IDENTIFIER_BEGIN= '{'; + private static final char IDENTIFIER_END= '}'; + + /** a buffer for the translation result string */ + private final StringBuffer fBuffer= new StringBuffer(); + /** position offsets of variables */ + private final Vector fOffsets= new Vector(); + /** position lengths of variables */ + private final Vector fLengths= new Vector(); + + /** the current parsing state */ + private int fState; + /** the last translation error */ + private String fErrorMessage; + + /** + * Returns an error message if an error occured for the last translation, null + * otherwise. + */ + public String getErrorMessage() { + return fErrorMessage; + } + + /** + * Translates a template string to TemplateBuffer. null + * is returned if there was an error. getErrorMessage() retrieves the + * associated error message. + * + * @param string the string to translate. + * @return returns the template buffer corresponding to the string, null + * if there was an error. + * @see getErrorMessage() + */ + public TemplateBuffer translate(String string) throws CoreException { + + fBuffer.setLength(0); + fOffsets.clear(); + fLengths.clear(); + fState= TEXT; + fErrorMessage= null; + + if (!parse(string)) + return null; + + switch (fState) { + case TEXT: + break; + + // illegal, but be tolerant + case ESCAPE: + fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$ + fBuffer.append(ESCAPE_CHARACTER); + return null; + + // illegal, but be tolerant + case IDENTIFIER: + fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$ + fBuffer.append(ESCAPE_CHARACTER); + return null; + } + + int[] offsets= new int[fOffsets.size()]; + int[] lengths= new int[fLengths.size()]; + + for (int i= 0; i < fOffsets.size(); i++) { + offsets[i]= ((Integer) fOffsets.get(i)).intValue(); + lengths[i]= ((Integer) fLengths.get(i)).intValue(); + } + + String translatedString= fBuffer.toString(); + TemplatePosition[] variables= findVariables(translatedString, offsets, lengths); + + return new TemplateBuffer(translatedString, variables); + } + + private static TemplatePosition[] findVariables(String string, int[] offsets, int[] lengths) { + + Map map= new HashMap(); + + for (int i= 0; i != offsets.length; i++) { + int offset= offsets[i]; + int length= lengths[i]; + + String content= string.substring(offset, offset + length); + Vector vector= (Vector) map.get(content); + if (vector == null) { + vector= new Vector(); + map.put(content, vector); + } + vector.add(new Integer(offset)); + } + + TemplatePosition[] variables= new TemplatePosition[map.size()]; + int k= 0; + + Set keys= map.keySet(); + for (Iterator i= keys.iterator(); i.hasNext(); ) { + String name= (String) i.next(); + Vector vector= (Vector) map.get(name); + + int[] offsets_= new int[vector.size()]; + for (int j= 0; j != offsets_.length; j++) + offsets_[j]= ((Integer) vector.get(j)).intValue(); + + variables[k]= new TemplatePosition(name, name, offsets_, name.length()); + k++; + } + + return variables; + } + + /** internal parser */ + private boolean parse(String string) { + + for (int i= 0; i != string.length(); i++) { + char ch= string.charAt(i); + + switch (fState) { + case TEXT: + switch (ch) { + case ESCAPE_CHARACTER: + fState= ESCAPE; + break; + + default: + fBuffer.append(ch); + break; + } + break; + + case ESCAPE: + switch (ch) { + case ESCAPE_CHARACTER: + fBuffer.append(ch); + fState= TEXT; + break; + + case IDENTIFIER_BEGIN: + fOffsets.add(new Integer(fBuffer.length())); + fState= IDENTIFIER; + break; + + default: + // illegal single escape character, but be tolerant + fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$ + fBuffer.append(ESCAPE_CHARACTER); + fBuffer.append(ch); + fState= TEXT; + return false; + } + break; + + case IDENTIFIER: + switch (ch) { + case IDENTIFIER_END: + int offset = ((Integer) fOffsets.get(fOffsets.size() - 1)).intValue(); + fLengths.add(new Integer(fBuffer.length() - offset)); + fState= TEXT; + break; + + default: + if (!Character.isUnicodeIdentifierStart((char) ch) && + !Character.isUnicodeIdentifierPart((char) ch)) + { + // illegal identifier character + fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.invalid.identifier"); //$NON-NLS-1$ + return false; + } + + fBuffer.append(ch); + break; + } + break; + } + } + + return true; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateVariable.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateVariable.java new file mode 100644 index 00000000000..dd1f650d0e4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/TemplateVariable.java @@ -0,0 +1,65 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A template variable. + */ +public abstract class TemplateVariable { + + /** name of the variable */ + private final String fName; + + /** description of the variable */ + private final String fDescription; + + /** + * Creates an instance of TemplateVariable. + * + * @param name the name of the variable + * @param description the description for the variable + */ + protected TemplateVariable(String name, String description) { + fName= name; + fDescription= description; + } + + /** + * Returns the name of the variable. + */ + public String getName() { + return fName; + } + + /** + * Returns the description for the variable. + */ + public String getDescription() { + return fDescription; + } + + /** + * Tests if this variable can be evaluated. + */ +// public abstract boolean canEvaluate(TemplateContext context); + + /** + * Evaluates this variable + * + * @return the evaluated string, or null if not evaluatable. + */ + public abstract String evaluate(TemplateContext context); + + /** + * Returns whether this variable is resolved. + * By default, the variable is not resolved. + * Clients can overwrite this method to force resolution of the variable. + */ + public boolean isResolved(TemplateContext context) { + return false; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Templates.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Templates.java new file mode 100644 index 00000000000..d9ed70f665f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/Templates.java @@ -0,0 +1,96 @@ +package org.eclipse.cdt.internal.corext.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import java.io.File; +import java.io.InputStream; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.jface.dialogs.ErrorDialog; + +/** + * Templates gives access to the available templates. + */ +public class Templates extends TemplateSet { + + private static final String DEFAULT_FILE= "default-templates.xml"; //$NON-NLS-1$ + private static final String TEMPLATE_FILE= "templates.xml"; //$NON-NLS-1$ + + /** Singleton. */ + private static Templates fgTemplates; + + /** + * Returns an instance of templates. + */ + public static Templates getInstance() { + if (fgTemplates == null) + fgTemplates= create(); + + return fgTemplates; + } + + private static Templates create() { + Templates templates= new Templates(); + + try { + File templateFile= getTemplateFile(); + if (templateFile.exists()) { + templates.addFromFile(templateFile); + } else { + templates.addFromStream(getDefaultsAsStream()); + templates.saveToFile(templateFile); + } + + } catch (CoreException e) { + CPlugin.log(e); + ErrorDialog.openError(null, + TemplateMessages.getString("Templates.error.title"), //$NON-NLS-1$ + e.getMessage(), e.getStatus()); + + templates.clear(); + } + + return templates; + } + + /** + * Resets the template set. + */ + public void reset() throws CoreException { + clear(); + addFromFile(getTemplateFile()); + } + + /** + * Resets the template set with the default templates. + */ + public void restoreDefaults() throws CoreException { + clear(); + addFromStream(getDefaultsAsStream()); + } + + /** + * Saves the template set. + */ + public void save() throws CoreException { + saveToFile(getTemplateFile()); + } + + private static InputStream getDefaultsAsStream() { + return Templates.class.getResourceAsStream(DEFAULT_FILE); + } + + private static File getTemplateFile() { + IPath path= CPlugin.getDefault().getStateLocation(); + path= path.append(TEMPLATE_FILE); + + return path.toFile(); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContext.java new file mode 100644 index 00000000000..4df0103341a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContext.java @@ -0,0 +1,102 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.ITemplateEditor; +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.corext.template.TemplateBuffer; +import org.eclipse.cdt.internal.corext.template.TemplateTranslator; +import org.eclipse.cdt.internal.corext.textmanipulation.TextBuffer; +import org.eclipse.cdt.internal.corext.textmanipulation.TextUtil; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.core.runtime.CoreException; + + + +/** + * A context for c/c++ + */ +public class CContext extends CompilationUnitContext { + + /** + * Creates a javadoc template context. + * + * @param type the context type. + * @param string the document string. + * @param completionPosition the completion position within the document. + * @param unit the compilation unit (may be null). + */ + public CContext(ContextType type, String string, int completionPosition, + ICompilationUnit compilationUnit) + { + super(type, string, completionPosition, compilationUnit); + } + + /* + * @see DocumentTemplateContext#getStart() + */ + public int getStart() { + String string= getString(); + int start= getCompletionPosition(); + + while ((start != 0) && Character.isUnicodeIdentifierPart(string.charAt(start - 1))) + start--; + + if ((start != 0) && Character.isUnicodeIdentifierStart(string.charAt(start - 1))) + start--; + + return start; + } + + /** + * Returns the indentation level at the position of code completion. + */ + public int getIndentationLevel() { + String string= getString(); + int start= getStart(); + + try { + TextBuffer textBuffer= TextBuffer.create(string); + String lineContent= textBuffer.getLineContentOfOffset(start); + + return TextUtil.getIndent(lineContent, CPlugin.getDefault().getPreferenceStore().getInt(CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH)); + + } catch (CoreException e) { + return 0; + } + } + + /* + * @see TemplateContext#canEvaluate(Template templates) + */ + public boolean canEvaluate(Template template) { + return template.matches(getKey(), getContextType().getName()); + } + + /* + * @see TemplateContext#evaluate(Template) + */ + public TemplateBuffer evaluate(Template template) throws CoreException { + if (!canEvaluate(template)) + return null; + + TemplateTranslator translator= new TemplateTranslator(); + TemplateBuffer buffer= translator.translate(template.getPattern()); + + getContextType().edit(buffer, this); + + ITemplateEditor formatter= new CFormatter(); + formatter.edit(buffer, this); + + return buffer; + } + +} + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContextType.java new file mode 100644 index 00000000000..9ffc3a9214d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CContextType.java @@ -0,0 +1,49 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.TemplateContext; + + +/** + * A context type for javadoc. + */ +public class CContextType extends CompilationUnitContextType { + + /** + * Creates a C context type. + */ + public CContextType() { + super("C"); + + // global + addVariable(new GlobalVariables.Cursor()); + addVariable(new GlobalVariables.Dollar()); + addVariable(new GlobalVariables.Date()); + addVariable(new GlobalVariables.Time()); + addVariable(new GlobalVariables.User()); + + // compilation unit + addVariable(new File()); + /* addVariable(new Method()); + addVariable(new ReturnType()); + addVariable(new Arguments()); + addVariable(new Type()); + addVariable(new Package()); */ + addVariable(new Project()); + // @@@ Need to add some specific C ones + } + + /* + * @see ContextType#createContext() + */ + public TemplateContext createContext() { + return new CContext(this, fString, fPosition, fCompilationUnit); + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java new file mode 100644 index 00000000000..dd0629bd4af --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java @@ -0,0 +1,197 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.ITemplateEditor; +import org.eclipse.cdt.internal.corext.template.TemplateBuffer; +import org.eclipse.cdt.internal.corext.template.TemplateContext; +import org.eclipse.cdt.internal.corext.template.TemplatePosition; +import org.eclipse.cdt.internal.corext.textmanipulation.MultiTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.NopTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.SimpleTextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.TextBuffer; +import org.eclipse.cdt.internal.corext.textmanipulation.TextBufferEditor; +import org.eclipse.cdt.internal.corext.textmanipulation.TextEdit; +import org.eclipse.cdt.internal.corext.textmanipulation.TextRegion; +import org.eclipse.cdt.internal.corext.textmanipulation.TextUtil; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Vector; + +import org.eclipse.core.runtime.CoreException; + + +/** + * A template editor using the Java formatter to format a template buffer. + */ +public class CFormatter implements ITemplateEditor { + + private static final String CURSOR= "cursor"; //$NON-NLS-1$ + private static final String MARKER= "/*${cursor}*/"; //$NON-NLS-1$ + + /* + * @see ITemplateEditor#edit(TemplateBuffer, TemplateContext) + */ + public void edit(TemplateBuffer buffer, TemplateContext context) throws CoreException { + int indentationLevel= ((CContext) context).getIndentationLevel(); + + //if (TemplatePreferencePage.useCodeFormatter()) + // format(buffer, indentationLevel); + //else + indentate(buffer, indentationLevel); + + trimBegin(buffer); + } + + private static int getCaretOffset(TemplatePosition[] variables) { + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + if (variable.getName().equals(CURSOR)) + return variable.getOffsets()[0]; + } + + return -1; + } + + + private static void indentate(TemplateBuffer templateBuffer, int indentationLevel) throws CoreException { + + String string= templateBuffer.getString(); + TemplatePosition[] variables= templateBuffer.getVariables(); + String indentation= TextUtil.createIndentString(indentationLevel); + + MultiTextEdit positions= variablesToPositions(variables); + MultiTextEdit multiEdit= new MultiTextEdit(); + + TextBuffer textBuffer= TextBuffer.create(string); + int lineCount= textBuffer.getNumberOfLines(); + for (int i= 0; i < lineCount; i++) { + TextRegion region= textBuffer.getLineInformation(i); + multiEdit.add(SimpleTextEdit.createInsert(region.getOffset(), indentation)); + } + + string= edit(string, positions, multiEdit); + positionsToVariables(positions, variables); + + templateBuffer.setContent(string, variables); + } + + private static void trimBegin(TemplateBuffer templateBuffer) throws CoreException { + String string= templateBuffer.getString(); + TemplatePosition[] variables= templateBuffer.getVariables(); + + MultiTextEdit positions= variablesToPositions(variables); + + int i= 0; + while ((i != string.length()) && Character.isWhitespace(string.charAt(i))) + i++; + + string= edit(string, positions, SimpleTextEdit.createDelete(0, i)); + positionsToVariables(positions, variables); + + templateBuffer.setContent(string, variables); + } + + private static String edit(String string, MultiTextEdit positions, MultiTextEdit multiEdit) throws CoreException { + TextBuffer textBuffer= TextBuffer.create(string); + TextBufferEditor editor= new TextBufferEditor(textBuffer); + editor.add(positions); + editor.add(multiEdit); + editor.performEdits(null); + + return textBuffer.getContent(); + } + + private static String edit(String string, MultiTextEdit positions, TextEdit singleEdit) throws CoreException { + TextBuffer textBuffer= TextBuffer.create(string); + TextBufferEditor editor= new TextBufferEditor(textBuffer); + editor.add(positions); + editor.add(singleEdit); + editor.performEdits(null); + + return textBuffer.getContent(); + } + + private static int[] variablesToOffsets(TemplatePosition[] variables) { + Vector vector= new Vector(); + for (int i= 0; i != variables.length; i++) { + int[] offsets= variables[i].getOffsets(); + for (int j= 0; j != offsets.length; j++) + vector.add(new Integer(offsets[j])); + } + + int[] offsets= new int[vector.size()]; + for (int i= 0; i != offsets.length; i++) + offsets[i]= ((Integer) vector.get(i)).intValue(); + + Arrays.sort(offsets); + + return offsets; + } + + private static void offsetsToVariables(int[] allOffsets, TemplatePosition[] variables) { + int[] currentIndices= new int[variables.length]; + for (int i= 0; i != currentIndices.length; i++) + currentIndices[i]= 0; + + int[][] offsets= new int[variables.length][]; + for (int i= 0; i != variables.length; i++) + offsets[i]= variables[i].getOffsets(); + + for (int i= 0; i != allOffsets.length; i++) { + + int min= Integer.MAX_VALUE; + int minVariableIndex= -1; + for (int j= 0; j != variables.length; j++) { + int currentIndex= currentIndices[j]; + + // determine minimum + if (currentIndex == offsets[j].length) + continue; + + int offset= offsets[j][currentIndex]; + + if (offset < min) { + min= offset; + minVariableIndex= j; + } + } + + offsets[minVariableIndex][currentIndices[minVariableIndex]]= allOffsets[i]; + currentIndices[minVariableIndex]++; + } + + for (int i= 0; i != variables.length; i++) + variables[i].setOffsets(offsets[i]); + } + + private static MultiTextEdit variablesToPositions(TemplatePosition[] variables) { + MultiTextEdit positions= new MultiTextEdit(); + for (int i= 0; i != variables.length; i++) { + int[] offsets= variables[i].getOffsets(); + for (int j= 0; j != offsets.length; j++) + positions.add(new NopTextEdit(offsets[j], 0)); + } + + return positions; + } + + private static void positionsToVariables(MultiTextEdit positions, TemplatePosition[] variables) { + Iterator iterator= positions.iterator(); + + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + int[] offsets= new int[variable.getOffsets().length]; + for (int j= 0; j != offsets.length; j++) + offsets[j]= ((TextEdit) iterator.next()).getTextRange().getOffset(); + + variable.setOffsets(offsets); + } + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContext.java new file mode 100644 index 00000000000..37a056eb658 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContext.java @@ -0,0 +1,66 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.DocumentTemplateContext; + + +/** + * A compilation unit context. + */ +public abstract class CompilationUnitContext extends DocumentTemplateContext { + + /** The compilation unit, may be null. */ + private final ICompilationUnit fCompilationUnit; + + /** + * Creates a compilation unit context. + * + * @param type the context type. + * @param string the document string. + * @param completionPosition the completion position within the document. + * @param compilationUnit the compilation unit (may be null). + */ + protected CompilationUnitContext(ContextType type, String string, int completionPosition, + ICompilationUnit compilationUnit) + { + super(type, string, completionPosition); + fCompilationUnit= compilationUnit; + } + + /** + * Returns the compilation unit if one is associated with this context, null otherwise. + */ + public final ICompilationUnit getCompilationUnit() { + return fCompilationUnit; + } + + /** + * Returns the enclosing element of a particular element type, null + * if no enclosing element of that type exists. + */ + public ICElement findEnclosingElement(int elementType) { + if (fCompilationUnit == null) + return null; + + /* try { + ICElement element= fCompilationUnit.getElementAt(getStart()); + while (element != null && element.getElementType() != elementType) + element= element.getParent(); + + return element; + + } catch (JavaModelException e) { + return null; + } */ + return null; + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContextType.java new file mode 100644 index 00000000000..877b1f33fca --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CompilationUnitContextType.java @@ -0,0 +1,180 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.TemplateContext; +import org.eclipse.cdt.internal.corext.template.TemplateVariable; + + +/** + * Compilation unit context type. + */ +public abstract class CompilationUnitContextType extends ContextType { + + /** the document string */ + protected String fString; + + /** the completion position within the document string */ + protected int fPosition; + + /** the associated compilation unit, may be null */ + protected ICompilationUnit fCompilationUnit; + + protected static class ReturnType extends TemplateVariable { + public ReturnType() { + super("return_type", TemplateMessages.getString("JavaContextType.variable.description.return.type")); + } + public String evaluate(TemplateContext context) { + /* IJavaElement element= ((CompilationUnitContext) context).findEnclosingElement(IJavaElement.METHOD); + if (element == null) + return null; + + try { + return Signature.toString(((IMethod) element).getReturnType()); + } catch (JavaModelException e) { + return null; + } */ + return null; + } + public boolean isResolved(TemplateContext context) { + return evaluate(context) != null; + } + } + + protected static class File extends TemplateVariable { + public File() { + super("file", TemplateMessages.getString("JavaContextType.variable.description.file")); + } + public String evaluate(TemplateContext context) { + //ICompilationUnit unit= ((CompilationUnitContext) context).getCompilationUnit(); + + //return (unit == null) ? null : unit.getElementName(); + return null; + } + public boolean isResolved(TemplateContext context) { + return evaluate(context) != null; + } + } + + protected static class EnclosingJavaElement extends TemplateVariable { + protected final int fElementType; + + public EnclosingJavaElement(String name, String description, int elementType) { + super(name, description); + fElementType= elementType; + } + public String evaluate(TemplateContext context) { + /*IJavaElement element= ((CompilationUnitContext) context).findEnclosingElement(fElementType); + return (element == null) ? null : element.getElementName(); */ + return null; + } + public boolean isResolved(TemplateContext context) { + return evaluate(context) != null; + } + } + + protected static class Method extends EnclosingJavaElement { + public Method() { + //super("enclosing_method", TemplateMessages.getString("JavaContextType.variable.description.enclosing.method"), IJavaElement.METHOD); + super("enclosing_method", TemplateMessages.getString("JavaContextType.variable.description.enclosing.method"), 0); + } + } + + protected static class Type extends EnclosingJavaElement { + public Type() { + super("enclosing_type", TemplateMessages.getString("JavaContextType.variable.description.enclosing.type"), 0); + } + } +/* + protected static class SuperClass extends EnclosingJavaElement { + public Type() { + super("super_class", TemplateMessages.getString("JavaContextType.variable.description.type"), IJavaElement.TYPE); + } + } +*/ + protected static class Package extends EnclosingJavaElement { + public Package() { + super("enclosing_package", TemplateMessages.getString("JavaContextType.variable.description.enclosing.package"), 0); + } + } + + protected static class Project extends EnclosingJavaElement { + public Project() { + super("enclosing_project", TemplateMessages.getString("JavaContextType.variable.description.enclosing.project"), 0); + } + } +/* + protected static class Project2 extends TemplateVariable { + public Project2() { + super("project", TemplateMessages.getString("JavaContextType.variable.description.project")); + } + public String evaluate(TemplateContext context) { + ICompilationUnit unit= ((JavaContext) context).getUnit(); + return (unit == null) ? null : unit.getJavaProject().getElementName(); + } + } +*/ + protected static class Arguments extends TemplateVariable { + public Arguments() { + super("enclosing_method_arguments", TemplateMessages.getString("JavaContextType.variable.description.enclosing.method.arguments")); + } + public String evaluate(TemplateContext context) { + /*IJavaElement element= ((CompilationUnitContext) context).findEnclosingElement(IJavaElement.METHOD); + if (element == null) + return null; + + IMethod method= (IMethod) element; + + try { + String[] arguments= method.getParameterNames(); + StringBuffer buffer= new StringBuffer(); + + for (int i= 0; i < arguments.length; i++) { + if (i > 0) + buffer.append(", "); + buffer.append(arguments[i]); + } + + return buffer.toString(); + + } catch (JavaModelException e) { + return null; + } */ + return null; + } + } + +/* + protected static class Line extends TemplateVariable { + public Line() { + super("line", TemplateMessages.getString("CompilationUnitContextType.variable.description.line")); + } + public String evaluate(TemplateContext context) { + return ((JavaTemplateContext) context).guessLineNumber(); + } + } +*/ + + /* + * @see ContextType#ContextType(String) + */ + public CompilationUnitContextType(String name) { + super(name); + } + + /** + * Sets context parameters. Needs to be called before createContext(). + */ + public void setContextParameters(String string, int position, ICompilationUnit compilationUnit) { + fString= string; + fPosition= position; + fCompilationUnit= compilationUnit; + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CppContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CppContextType.java new file mode 100644 index 00000000000..540b2f446ac --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CppContextType.java @@ -0,0 +1,47 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.TemplateContext; + +/** + * A context type for javadoc. + */ +public class CppContextType extends CompilationUnitContextType { + + /** + * Creates a C context type. + */ + public CppContextType() { + super("C++"); + + // global + addVariable(new GlobalVariables.Cursor()); + addVariable(new GlobalVariables.Dollar()); + addVariable(new GlobalVariables.Date()); + addVariable(new GlobalVariables.Time()); + addVariable(new GlobalVariables.User()); + + // compilation unit + addVariable(new File()); + /* addVariable(new Method()); + addVariable(new ReturnType()); + addVariable(new Arguments()); + addVariable(new Type()); + addVariable(new Package()); */ + addVariable(new Project()); + // @@@ Need to add some specific C ones + } + + /* + * @see ContextType#createContext() + */ + public TemplateContext createContext() { + return new CContext(this, fString, fPosition, fCompilationUnit); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/GlobalVariables.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/GlobalVariables.java new file mode 100644 index 00000000000..4c276d16ff9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/GlobalVariables.java @@ -0,0 +1,80 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.SimpleTemplateVariable; +import org.eclipse.cdt.internal.corext.template.TemplateContext; +import java.text.DateFormat; + + +/** + * Global variables which are available in any context. + */ +public class GlobalVariables { + + /** + * The cursor variable determines the cursor placement after template edition. + */ + static class Cursor extends SimpleTemplateVariable { + public Cursor() { + super("cursor", TemplateMessages.getString("GlobalVariables.variable.description.cursor")); + setEvaluationString(""); + setResolved(true); + } + } + + /** + * The dollar variable inserts an escaped dollar symbol. + */ + static class Dollar extends SimpleTemplateVariable { + public Dollar() { + super("dollar", TemplateMessages.getString("GlobalVariables.variable.description.dollar")); + setEvaluationString("$"); + setResolved(true); + } + } + + /** + * The date variable evaluates to the current date. + */ + static class Date extends SimpleTemplateVariable { + public Date() { + super("date", TemplateMessages.getString("GlobalVariables.variable.description.date")); + setResolved(true); + } + public String evaluate(TemplateContext context) { + return DateFormat.getDateInstance().format(new java.util.Date()); + } + } + + /** + * The time variable evaluates to the current time. + */ + static class Time extends SimpleTemplateVariable { + public Time() { + super("time", TemplateMessages.getString("GlobalVariables.variable.description.time")); + setResolved(true); + } + public String evaluate(TemplateContext context) { + return DateFormat.getTimeInstance().format(new java.util.Date()); + } + } + + /** + * The user variable evaluates to the current user. + */ + static class User extends SimpleTemplateVariable { + public User() { + super("user", TemplateMessages.getString("GlobalVariables.variable.description.user")); + setResolved(true); + } + public String evaluate(TemplateContext context) { + return System.getProperty("user.name"); + } + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/ICompilationUnit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/ICompilationUnit.java new file mode 100644 index 00000000000..872ed89bb8c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/ICompilationUnit.java @@ -0,0 +1,11 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +public interface ICompilationUnit { + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java new file mode 100644 index 00000000000..49fdc795f12 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java @@ -0,0 +1,46 @@ +package org.eclipse.cdt.internal.corext.template.c; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TemplateMessages { + + private static final String RESOURCE_BUNDLE= TemplateMessages.class.getName(); + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private TemplateMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + */ + public static String getFormattedString(String key, Object arg) { + return MessageFormat.format(getString(key), new Object[] { arg }); + } + + + /** + * Gets a string from the resource bundle and formats it with arguments + */ + public static String getFormattedString(String key, Object[] args) { + return MessageFormat.format(getString(key), args); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties new file mode 100644 index 00000000000..6a95267b954 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties @@ -0,0 +1,29 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +GlobalVariables.variable.description.dollar=The dollar symbol +GlobalVariables.variable.description.cursor=The cursor position after editing template variables + +GlobalVariables.variable.description.line=Current line number +GlobalVariables.variable.description.date=Current date +GlobalVariables.variable.description.time=Current time +GlobalVariables.variable.description.user=User name + +JavaDocContextType.variable.description.file=Filename of compilation unit + +JavaContextType.variable.description.file=Filename of compilation unit +JavaContextType.variable.description.array=A proposal for an array +JavaContextType.variable.description.array.type=A proposal for the element type of an array +JavaContextType.variable.description.array.element=A proposal for the element name of an array +JavaContextType.variable.description.index=A proposal for an index (int) +JavaContextType.variable.description.collector=A proposal for a collector (java.util.Collector) +JavaContextType.variable.description.iterator=A proposal for an iterator (java.util.Iterator) +JavaContextType.variable.description.arguments=Method arguments (evaluates to empty string) +JavaContextType.variable.description.enclosing.method=Enclosing method name +JavaContextType.variable.description.enclosing.type=Enclosing type name +JavaContextType.variable.description.enclosing.package=Enclosing package name +JavaContextType.variable.description.enclosing.project=Enclosing project name +JavaContextType.variable.description.enclosing.method.arguments=Argument names of enclosing method +JavaContextType.variable.description.return.type=Enclosing method return type diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/default-templates.xml b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/default-templates.xml new file mode 100644 index 00000000000..9508183d208 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/default-templates.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/ISourceRange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/ISourceRange.java new file mode 100644 index 00000000000..73d08927f27 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/ISourceRange.java @@ -0,0 +1,28 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A source range defines an element's source coordinates relative to + * its source buffer. + *

+ * This interface is not intended to be implemented by clients. + *

+ */ +public interface ISourceRange { + +/** + * Returns the number of characters of the source code for this element, + * relative to the source buffer in which this element is contained. + */ +int getLength(); +/** + * Returns the 0-based index of the first character of the source code for this element, + * relative to the source buffer in which this element is contained. + */ +int getOffset(); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/Messages.properties new file mode 100644 index 00000000000..729774b29aa --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/Messages.properties @@ -0,0 +1,17 @@ +################################################################################ +# Copyright (c) 2002 International Business Machines Corp. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v0.5 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v05.html +# +# Contributors: +# IBM Corporation - initial API and implementation +################################################################################ + +TextRange.offset=Offset: +TextRange.length=\ Length: + +TextBuffer.wrongRange=Replace failed due to wrong range [{0},{1}] + +TextBufferFactory.bufferNotManaged=Buffer not managed diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MoveTextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MoveTextEdit.java new file mode 100644 index 00000000000..0dc8a460167 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MoveTextEdit.java @@ -0,0 +1,146 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.util.Assert; + +/** + * A text edit that moves text inside a text buffer. + */ +public final class MoveTextEdit extends TextEdit { + + /* package */ static class TargetMark extends NopTextEdit { + private MoveTextEdit fMoveTextEdit; + public TargetMark(TextRange range, MoveTextEdit edit) { + super(range); + fMoveTextEdit= edit; + } + /* package */ MoveTextEdit getMoveTextEdit() { + return fMoveTextEdit; + } + public TextEdit perform(TextBuffer buffer) throws CoreException { + fMoveTextEdit.internalPerform(buffer); + return super.perform(buffer); + } + public TextEdit copy() { + Assert.isTrue(false, "This should never happen"); //$NON-NLS-1$ + return super.copy(); + } + } + + private TextRange fTarget; + private TextRange fSource; + private int fPerformCounter; + + /** + * Creates a new MoveTextEdit. The text edit doesn't support + * overlapping moves. So for a MoveTextEdit destination <= offset && + * offset + length - 1 <= destination must be true. + * + * @param offset the offset of the text to be moved + * @param length the text length to be moved + * @param destination the destination offset + */ + public MoveTextEdit(int offset, int length, int destination) { + Assert.isTrue(destination <= offset || offset + length <= destination); + fSource= new TextRange(offset, length); + fTarget= new TextRange(destination); + } + + /** + * Creates a new MoveTextEdit with the given source and target range. + * + * @param source the source + * @param target the target + */ + private MoveTextEdit(TextRange source,TextRange target) { + fSource= source; + fTarget= target; + } + + /** + * Returns the move text edit's source range. This method returns the same range + * as TextEdit#getTextRange() + * + * @return the edit's source range + */ + public TextRange getSourceRange() { + return fSource; + } + + /** + * Returns the move text edit's target range. + * + * @return the edit's target range + */ + public TextRange getTargetRange() { + return fTarget; + } + + /* non Java-doc + * @see TextEdit#getTextRange() + */ + public TextRange getTextRange() { + return fSource; + } + + /* non Java-doc + * @see TextEdit#connect(TextBufferEditor) + */ + public void connect(TextBufferEditor editor) throws CoreException { + editor.add(new TargetMark(fTarget, this)); + } + + /* non Java-doc + * @see TextEdit#perform(TextBuffer) + */ + public TextEdit perform(TextBuffer buffer) throws CoreException { + internalPerform(buffer); + return new MoveTextEdit(fTarget, fSource); + } + + /* non Java-doc + * @see TextEdit#copy() + */ + public TextEdit copy() { + TextRange source= getSourceRange(); + TextRange target= getTargetRange(); + return new MoveTextEdit(source.fOffset, source.fLength, target.fOffset); + } + + //---- Helper method --------------------------------------------------------------------------------- + + private void internalPerform(TextBuffer buffer) throws CoreException { + Assert.isTrue(fPerformCounter < 2); + if (++fPerformCounter == 2) { + TextRange source= getSourceRange(); + TextRange target= getTargetRange(); + String current= buffer.getContent(source.fOffset, source.fLength); + buffer.replace(source, ""); //$NON-NLS-1$ + buffer.replace(target, current); + } + } + + /* package */ boolean isUpMove() { + return fSource.fOffset < fTarget.fOffset; + } + + /* package */ boolean isDownMove() { + return fSource.fOffset > fTarget.fOffset; + } + + /* package */ TextRange getChildRange() { + int offset= fSource.fOffset; + int length= fSource.fLength; + int destination= fTarget.fOffset; + if (destination <= offset) + return new TextRange(destination, offset + length - destination); + else + return new TextRange(offset, destination - offset); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MultiTextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MultiTextEdit.java new file mode 100644 index 00000000000..dd056ff4c8f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/MultiTextEdit.java @@ -0,0 +1,136 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.internal.utils.Assert; +import org.eclipse.core.runtime.CoreException; + +public class MultiTextEdit { + + private List fChildren; + + /** + * Creates a new composite text edit. + */ + public MultiTextEdit() { + fChildren= new ArrayList(3); + } + + protected MultiTextEdit(List children) throws CoreException { + fChildren= new ArrayList(children.size()); + for (Iterator iter= children.iterator(); iter.hasNext();) { + fChildren.add(((TextEdit)iter.next()).copy()); + } + } + + protected List getChildren() { + return fChildren; + } + + /** + * Adds all TextEdits managed by the given multt text edit. + * + * @param edit the multi text edit to be added. + */ + public void add(MultiTextEdit edit) { + Assert.isNotNull(edit); + fChildren.add(edit); + } + + /** + * Adds a text edit. + * + * @param edit the text edit to be added + */ + public void add(TextEdit edit) { + Assert.isNotNull(edit); + fChildren.add(edit); + } + + /** + * Returns the children managed by this text edit collection. + * + * @return the children of this composite text edit + */ + public Iterator iterator() { + return fChildren.iterator(); + } + + /** + * Connects this text edit to the given TextBufferEditor. + * Note that this method should only be called by a + * TextBufferEditor. + *

+ * This default implementation does nothing. Subclasses may override + * if needed. + * + * @param editor the text buffer editor this text edit has been added to + */ + public void connect(TextBufferEditor editor) throws CoreException { + for (Iterator iter= fChildren.iterator(); iter.hasNext();) { + Object element= iter.next(); + if (element instanceof TextEdit) + editor.add((TextEdit)element); + else + editor.add((MultiTextEdit)element); + } + } + + /** + * Creates and returns a copy of this text edit collection. The copy method should + * be implemented in a way so that the copy can be added to a different + * TextBuffer without causing any harm to the object from which the copy + * has been created. + * + * @return a copy of this object. + */ + public MultiTextEdit copy() throws CoreException { + return new MultiTextEdit(fChildren); + } + + /** + * Returns the TextRange that this text edit is going to + * manipulate. If this method is called before the MultiTextEdit + * has been added to a TextBufferEditor it may return + * null to indicate this situation. + * + * @return the TextRanges this TextEdit is going + * to manipulate + */ + public TextRange getTextRange() { + int size= fChildren.size(); + if (size == 0) + return new TextRange(0,0); + TextRange range= ((TextEdit)fChildren.get(0)).getTextRange(); + int start= range.getOffset(); + int end= range.getInclusiveEnd(); + for (int i= 1; i < size; i++) { + range= ((TextEdit)fChildren.get(i)).getTextRange(); + start= Math.min(start, range.getOffset()); + end= Math.max(end, range.getInclusiveEnd()); + } + return new TextRange(start, end - start + 1); + } + + /** + * Returns the element modified by this text edit. The method + * may return null if the modification isn't related to a + * element or if the content of the modified text buffer doesn't + * follow any syntax. + *

+ * This default implementation returns null + * + * @return the element modified by this text edit + */ + public Object getModifiedElement() { + return null; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/NopTextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/NopTextEdit.java new file mode 100644 index 00000000000..2b8fc3350aa --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/NopTextEdit.java @@ -0,0 +1,61 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; + +/** + * A text edit that does nothing. A NopTextEdit can be used to track + * positions when executing TextEdits associated with a + * TextBufferEditor. + */ +public class NopTextEdit extends TextEdit { + + private TextRange fTextRange; + + /** + * Creates a new NopTextEdit for the given + * offset and length. + * + * @param offset the starting offset this text edit is "working on" + * @param length the length this text edit is "working on" + */ + public NopTextEdit(int offset, int length) { + this(new TextRange(offset, length)); + } + + /** + * Creates a new NopTextEdit for the given + * range. + * + * @param range the TextRange this text edit is "working on" + */ + public NopTextEdit(TextRange range) { + fTextRange= range; + } + + /* non Java-doc + * @see TextEdit#getTextRange + */ + public TextRange getTextRange() { + return fTextRange; + } + + /* non Java-doc + * @see TextEdit#perform + */ + public TextEdit perform(TextBuffer buffer) throws CoreException { + return new NopTextEdit(fTextRange); + } + + /* non Java-doc + * @see TextEdit#perform + */ + public TextEdit copy() { + return new NopTextEdit(fTextRange.copy()); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SimpleTextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SimpleTextEdit.java new file mode 100644 index 00000000000..21ffb7a6b53 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SimpleTextEdit.java @@ -0,0 +1,106 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.util.Assert; + + +public abstract class SimpleTextEdit extends TextEdit { + + private TextRange fRange; + private String fText; + + public static SimpleTextEdit createReplace(int offset, int length, String text) { + return new SimpleTextEditImpl(offset, length, text); + } + + public static SimpleTextEdit createInsert(int offset, String text) { + return new SimpleTextEditImpl(offset, 0, text); + } + + public static SimpleTextEdit createDelete(int offset, int length) { + return new SimpleTextEditImpl(offset, length, ""); //$NON-NLS-1$ + } + + private final static class SimpleTextEditImpl extends SimpleTextEdit { + protected SimpleTextEditImpl(TextRange range, String text) { + super(range, text); + } + protected SimpleTextEditImpl(int offset, int length, String text) { + super(offset, length, text); + } + public TextEdit copy() { + return new SimpleTextEditImpl(getTextRange().copy(), getText()); + } + } + + protected SimpleTextEdit() { + this(TextRange.UNDEFINED, ""); //$NON-NLS-1$ + } + + protected SimpleTextEdit(int offset, int length, String text) { + this(new TextRange(offset, length), text); + } + protected SimpleTextEdit(TextRange range, String text) { + Assert.isNotNull(range); + Assert.isNotNull(text); + fRange= range; + fText= text; + } + + /** + * Returns the text edit's text + * + * @return the text edit's text + */ + public String getText() { + return fText; + } + + /** + * Sets the text edit's text + *

+ * This method should only be called from within the + * connect method. + * + * @param text the text edit's text + */ + protected final void setText(String text) { + fText= text; + Assert.isNotNull(fText); + } + + /** + * Sets the text edit's range. + *

+ * This method should only be called from within the + * connect method. + * + * @param range the text edit's range. + */ + protected void setTextRange(TextRange range) { + fRange= range; + Assert.isNotNull(fRange); + } + + /* non Java-doc + * @see TextEdit#getTextRange + */ + public TextRange getTextRange() { + return fRange; + } + + /* non Java-doc + * @see TextEdit#doPerform + */ + public final TextEdit perform(TextBuffer buffer) throws CoreException { + String current= buffer.getContent(fRange.fOffset, fRange.fLength); + buffer.replace(fRange, fText); + return new SimpleTextEditImpl(fRange, current); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SwapTextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SwapTextEdit.java new file mode 100644 index 00000000000..53693786816 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/SwapTextEdit.java @@ -0,0 +1,25 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A SwapTextEdit exchanges to text ranges. + */ +public class SwapTextEdit extends MultiTextEdit { + /** + * Create a new SwapTextEdit + * + * @param offset1 the offset of the first text range + * @param length1 the length of the first text range + * @param offset2 the offset of the second text range + * @param length2 the length of the second text range + */ + public SwapTextEdit(int offset1, int length1, int offset2, int length2) { + add(new MoveTextEdit(offset1, length1, offset2)); + add(new MoveTextEdit(offset2, length2, offset1)); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBuffer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBuffer.java new file mode 100644 index 00000000000..92183108577 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBuffer.java @@ -0,0 +1,451 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultLineTracker; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.util.Assert; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CStatusConstants; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + + +/** + * An implementation of a TextBuffer that is based on ITextSelection + * and IDocument. + */ +public class TextBuffer { + + private static class DocumentRegion extends TextRegion { + IRegion fRegion; + public DocumentRegion(IRegion region) { + fRegion= region; + } + public int getOffset() { + return fRegion.getOffset(); + } + public int getLength() { + return fRegion.getLength(); + } + } + + private IDocument fDocument; + + private static final TextBufferFactory fgFactory= new TextBufferFactory(); + + TextBuffer(IDocument document) { + fDocument= document; + Assert.isNotNull(fDocument); + } + + /** + * Returns the number of characters in this text buffer. + * + * @return the number of characters in this text buffer + */ + public int getLength() { + return fDocument.getLength(); + } + + /** + * Returns the number of lines in this text buffer. + * + * @return the number of lines in this text buffer + */ + public int getNumberOfLines() { + return fDocument.getNumberOfLines(); + } + + /** + * Returns the character at the given offset in this text buffer. + * + * @param offset a text buffer offset + * @return the character at the offset + * @exception IndexOutOfBoundsException if the offset + * argument is negative or not less than the length of this text buffer. + */ + public char getChar(int offset) { + try { + return fDocument.getChar(offset); + } catch (BadLocationException e) { + throw new ArrayIndexOutOfBoundsException(e.getMessage()); + } + } + + /** + * Returns the whole content of the text buffer. + * + * @return the whole content of the text buffer + */ + public String getContent() { + return fDocument.get(); + } + + /** + * Returns length characters starting from the specified position. + * + * @return the characters specified by the given text region. Returns + * null if text range is illegal + */ + public String getContent(int start, int length) { + try { + return fDocument.get(start, length); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns the preferred line delimiter to be used for this text buffer. + * + * @return the preferred line delimiter + */ + public String getLineDelimiter() { + String lineDelimiter= getLineDelimiter(0); + if (lineDelimiter == null) + lineDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + return lineDelimiter; + } + + /** + * Returns the line delimiter used for the given line number. Returns + * null if the line number is out of range. + * + * @return the line delimiter used by the given line number or null + */ + public String getLineDelimiter(int line) { + try { + return fDocument.getLineDelimiter(line); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns the line for the given line number. If there isn't any line for + * the given line number, null is returned. + * + * @return the line for the given line number or null + */ + public String getLineContent(int line) { + try { + IRegion region= fDocument.getLineInformation(line); + return fDocument.get(region.getOffset(), region.getLength()); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns the line indent for the given line. If there isn't any line for the + * given line number, -1 is returned. + * + * @return the line indent for the given line number of -1 + */ + public int getLineIndent(int lineNumber, int tabWidth) { + return getIndent(getLineContent(lineNumber), tabWidth); + } + + /** + * Returns a region of the specified line. The region contains the offset and the + * length of the line excluding the line's delimiter. Returns null + * if the line doesn't exist. + * + * @param line the line of interest + * @return a line description or null if the given line doesn't + * exist + */ + public TextRegion getLineInformation(int line) { + try { + return new DocumentRegion(fDocument.getLineInformation(line)); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns a line region of the specified offset. The region contains the offset and + * the length of the line excluding the line's delimiter. Returns null + * if the line doesn't exist. + * + * @param offset an offset into a line + * @return a line description or null if the given line doesn't + * exist + */ + public TextRegion getLineInformationOfOffset(int offset) { + try { + return new DocumentRegion(fDocument.getLineInformationOfOffset(offset)); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Returns the line number that contains the given position. If there isn't any + * line that contains the position, null is returned. The returned + * string is a copy and doesn't contain the line delimiter. + * + * @return the line that contains the given offset or null if line + * doesn't exist + */ + public int getLineOfOffset(int offset) { + try { + return fDocument.getLineOfOffset(offset); + } catch (BadLocationException e) { + return -1; + } + } + + /** + * Returns the line that contains the given position. If there isn't any + * line that contains the position, null is returned. The returned + * string is a copy and doesn't contain the line delimiter. + * + * @return the line that contains the given offset or null if line + * doesn't exist + */ + public String getLineContentOfOffset(int offset) { + try { + IRegion region= fDocument.getLineInformationOfOffset(offset); + return fDocument.get(region.getOffset(), region.getLength()); + } catch (BadLocationException e) { + return null; + } + } + + /** + * Converts the text determined by the region [offset, length] into an array of lines. + * The lines are copies of the original lines and don't contain any line delimiter + * characters. + * + * @return the text converted into an array of strings. Returns null if the + * region lies outside the source. + */ + public String[] convertIntoLines(int offset, int length) { + try { + String text= fDocument.get(offset, length); + ILineTracker tracker= new DefaultLineTracker(); + tracker.set(text); + int size= tracker.getNumberOfLines(); + String result[]= new String[size]; + for (int i= 0; i < size; i++) { + IRegion region= tracker.getLineInformation(i); + result[i]= getContent(offset + region.getOffset(), region.getLength()); + } + return result; + } catch (BadLocationException e) { + return null; + } + } + + /** + * Subsitutes the given text for the specified text position + * + * @param offset the starting offset of the text to be replaced + * @param length the length of the text to be replaced + * @param text the substitution text + * @exception CoreException if the text position [offset, length] is invalid. + */ + public void replace(int offset, int length, String text) throws CoreException { + try { + fDocument.replace(offset, length, text); + } catch (BadLocationException e) { + IStatus s= new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, CStatusConstants.INTERNAL_ERROR, + TextManipulationMessages.getFormattedString( + "TextBuffer.wrongRange", //$NON-NLS-1$ + new Object[] {new Integer(offset), new Integer(length) } ), e); + throw new CoreException(s); + } + } + + public void replace(TextRange range, String text) throws CoreException { + replace(range.fOffset, range.fLength, text); + } + + //---- Special methods used by the TextBufferEditor + + /** + * Releases this text buffer. + */ + /* package */ void release() { + } + + /* package */ void registerUpdater(IDocumentListener listener) { + fDocument.addDocumentListener(listener); + } + + /* package */ void unregisterUpdater(IDocumentListener listener) { + fDocument.removeDocumentListener(listener); + } + + //---- Utility methods + + /** + * Returns the indent for the given line. + * If line is null, -1 is returned. + * + * @param line the line for which the indent is determined + * @return the line indent for the given line number or -1 + */ + public static int getIndent(String line, int tabWidth) { + if (line == null) + return -1; + int indent= 0; + int blanks= 0; + int size= line.length(); + for (int i= 0; i < size; i++) { + switch (line.charAt(i)) { + case '\t': + indent++; + blanks= 0; + continue; + case ' ': + blanks++; + if (blanks == tabWidth) { + indent++; + blanks= 0; + } + continue; + default: + break; + } + break; + } + return indent; + } + + /** + * Returns a copy of the line with the given number of identations + * removed from the beginning. + * If the count is zero, the line is returned. + */ + public static String removeIndent(String line, int indentsToRemove, int tabWidth) { + if (line != null) { + int indent= 0; + int blanks= 0; + int size= line.length(); + for (int i= 0; i < size; i++) { + + if (indent >= indentsToRemove) { + line= line.substring(i); + break; + } + + switch (line.charAt(i)) { + case '\t': + indent++; + blanks= 0; + continue; + case ' ': + blanks++; + if (blanks == tabWidth) { + indent++; + blanks= 0; + } + continue; + default: + break; + } + } + } + return line; + } + + //---- Factory methods ---------------------------------------------------------------- + + /** + * Acquires a text buffer for the given file. If a text buffer for the given + * file already exists, then that one is returned. + * + * @param file the file for which a text buffer is requested + * @return a managed text buffer for the given file + * @exception CoreException if it was not possible to acquire the + * text buffer + */ + public static TextBuffer acquire(IFile file) throws CoreException { + return fgFactory.acquire(file); + } + + /** + * Releases the given text buffer. + * + * @param buffer the text buffer to be released + */ + public static void release(TextBuffer buffer) { + fgFactory.release(buffer); + } + + /** + * Commits the changes made to the given text buffer to the underlying + * storage system. + * + * @param buffer the text buffer containing the changes to be committed. + * @param force if true the text buffer is committed in any case. + * If false the text buffer is ONLY committed if the client + * is the last one that holds a reference to the text buffer. Clients of this + * method must make sure that they don't call this method from within an + * IWorkspaceRunnable. + * @param pm the progress monitor used to report progress if committing is + * necessary + */ + public static void commitChanges(TextBuffer buffer, boolean force, IProgressMonitor pm) throws CoreException { + fgFactory.commitChanges(buffer, force, pm); + } + + /** + * Creates a new TextBuffer for the given file. The returned + * buffer will not be managed. Any subsequent call to create + * with the same file will return a different text buffer. + *

+ * If the file is currently open in a text editor, the editors content is copied into + * the returned TextBuffer. Otherwise the content is read from + * disk. + * + * @param file the file for which a text buffer is to be created + * @return a new unmanaged text buffer + * @exception CoreException if it was not possible to create the text buffer + */ + public static TextBuffer create(IFile file) throws CoreException { + return fgFactory.create(file); + } + + /** + * Creates a new TextBuffer for the string. The returned + * buffer will not be managed. Any subsequent call to create + * with the same string will return a different text buffer. + * + * @param content the text buffer's content + * @return a new unmanaged text buffer + * @exception CoreException if it was not possible to create the text buffer + */ + public static TextBuffer create(String content) throws CoreException { + return fgFactory.create(content); + } + + // Unclear which methods are needed if we get the new save model. If optimal no + // save is needed at all. + + public static void save(TextBuffer buffer, IProgressMonitor pm) throws CoreException { + fgFactory.save(buffer, pm); + } + + public static void aboutToChange(TextBuffer buffer) throws CoreException { + fgFactory.aboutToChange(buffer); + } + + public static void changed(TextBuffer buffer) throws CoreException { + fgFactory.changed(buffer); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferEditor.java new file mode 100644 index 00000000000..d26ceafa187 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferEditor.java @@ -0,0 +1,218 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.util.Assert; + +import org.eclipse.cdt.internal.corext.textmanipulation.TextEditNode.RootNode; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CStatusConstants; +/** + * A TextBufferEditor manages a set of TextEdits and applies + * them as a whole to a TextBuffer. Added TextEdits must + * not overlap. The only exception from this rule are insertion point. There can be more than + * one insert point at the same text position. Clients should use the method + * canPerformEdits to validate if all added text edits follow these rules. + *

+ * Clients can attach more than one TextBufferEditor to a single + * TextBuffer. If so canPerformEdits validates all text edits from + * all text buffer editors working on the same text buffer. + */ +public class TextBufferEditor { + + private TextBuffer fBuffer; + private List fEdits; + private RootNode fRootNode; + private int fNumberOfNodes; + private int fConnectCount; + private int fMode; + + /* package */ static final int UNDEFINED= 0; + /* package */ static final int REDO= 1; + /* package */ static final int UNDO= 2; + + /** + * Creates a new TextBufferEditor for the given + * TextBuffer. + * + * @param the text buffer this editor is working on. + */ + public TextBufferEditor(TextBuffer buffer) { + fBuffer= buffer; + Assert.isNotNull(fBuffer); + fEdits= new ArrayList(); + } + + /** + * Returns the text buffer this editor is working on. + * + * @return the text buffer this editor is working on + */ + public TextBuffer getTextBuffer() { + return fBuffer; + } + + /** + * Adds a TextEdit to this text editor. Adding a TextEdit + * to a TextBufferEditor transfers ownership of the edit to the editor. So + * after a edit has been added to a editor the creator of that edit must not continue + * modifing it. + * + * @param edit the text edit to be added + * @exception CoreException if the text edit can not be added + * to this text buffer editor + */ + public void add(TextEdit edit) throws CoreException { + Assert.isTrue(fMode == UNDEFINED || fMode == REDO); + internalAdd(edit); + fMode= REDO; + } + + /** + * Adds a MultiTextEdit to this text editor. Adding a MultiTextEdit + * to a TextBufferEditor transfers ownership of the edit to the editor. So + * after a edit has been added to a editor the creator of that edit must not continue + * modifing it. + * + * @param edit the multi text edit to be added + * @exception CoreException if the multi text edit can not be added + * to this text buffer editor + */ + public void add(MultiTextEdit edit) throws CoreException { + Assert.isTrue(fMode == UNDEFINED || fMode == REDO); + edit.connect(this); + fMode= REDO; + } + + /** + * Adds a UndoMemento to this text editor. Adding a UndoMemento + * to a TextBufferEditor transfers ownership of the memento to the editor. So + * after a memento has been added to a editor the creator of that memento must not continue + * modifing it. + * + * @param undo the undo memento to be added + * @exception CoreException if the undo memento can not be added + * to this text buffer editor + */ + public void add(UndoMemento undo) throws CoreException { + Assert.isTrue(fMode == UNDEFINED); + List list= undo.fEdits; + // Add them reverse since we are adding undos. + for (int i= list.size() - 1; i >= 0; i--) { + internalAdd((TextEdit)list.get(i)); + } + fMode= undo.fMode; + } + + /** + * Checks if the TextEdit added to this text editor can be executed. + * + * @return true if the edits can be executed. Return false + * otherwise. One major reason why text edits cannot be executed + * is a wrong offset or length value of a TextEdit. + */ + public boolean canPerformEdits() { + if (fRootNode != null) + return true; + fRootNode= buildTree(); + if (fRootNode == null) + return false; + if (fRootNode.validate(fBuffer.getLength())) + return true; + + fRootNode= null; + return false; + } + + /** + * Clears the text buffer editor. + */ + public void clear() { + fRootNode= null; + fMode= UNDEFINED; + fEdits.clear(); + } + + /** + * Executes the text edits added to this text buffer editor and clears all added + * text edits. + * + * @param pm a progress monitor to report progress + * @return an object representing the undo of the executed TextEdits + * @exception CoreException if the edits cannot be executed + */ + public UndoMemento performEdits(IProgressMonitor pm) throws CoreException { + if (pm == null) + pm= new NullProgressMonitor(); + + int size= fEdits.size(); + if (size == 0) + return new UndoMemento(fMode == UNDO ? REDO : UNDO); + + if (fRootNode == null) { + fRootNode= buildTree(); + if (fRootNode == null || !fRootNode.validate(fBuffer.getLength())) { + IStatus s= new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, CStatusConstants.INTERNAL_ERROR, + "RootNode empty", null); + throw new CoreException(s); + } + } + try { + pm.beginTask("", fNumberOfNodes + 10); //$NON-NLS-1$ + UndoMemento undo= null; + if (fMode == REDO) { + undo= fRootNode.performDo(fBuffer, pm); + fRootNode.performedDo(); + } else { + undo= fRootNode.performUndo(fBuffer, pm); + fRootNode.performedUndo(); + } + pm.worked(10); + return undo; + } finally { + pm.done(); + clear(); + } + } + + //---- Helper methods ------------------------------------------------------------ + + private RootNode buildTree() { + TextEditNode[] nodes= new TextEditNode[fEdits.size()]; + for (int i= fEdits.size() - 1; i >= 0; i--) { + nodes[i]= TextEditNode.create((TextEdit)fEdits.get(i)); + } + fNumberOfNodes= nodes.length; + Arrays.sort(nodes, new TextEditNodeComparator()); + RootNode root= new RootNode(fBuffer.getLength()); + for (int i= 0; i < nodes.length; i++) { + root.add(nodes[i]); + } + return root; + } + + private void internalAdd(TextEdit edit) throws CoreException { + edit.index= fEdits.size(); + edit.isSynthetic= fConnectCount > 0; + try { + fConnectCount++; + edit.connect(this); + } finally { + fConnectCount--; + } + fEdits.add(edit); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferFactory.java new file mode 100644 index 00000000000..51675652050 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextBufferFactory.java @@ -0,0 +1,191 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CStatusConstants; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.util.Assert; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; + + +/* package */ class TextBufferFactory { + + private IDocumentProvider fDocumentProvider; + private Map fFileValueMap; + private Map fBufferValueMap; + + private static class Value { + TextBuffer buffer; + FileEditorInput input; + IDocument document; + IAnnotationModel annotationModel; + int references; + public Value(TextBuffer b, FileEditorInput i, IDocument d, IAnnotationModel m) { + buffer= b; + input= i; + document= d; + annotationModel= m; + } + } + + public TextBufferFactory() { + // XXX http://dev.eclipse.org/bugs/show_bug.cgi?id=5170 + // Need way to map a file to a document without knowing any kind of document provider. + this(CPlugin.getDefault().getDocumentProvider()); + } + + public TextBufferFactory(IDocumentProvider provider) { + fDocumentProvider= provider; + Assert.isNotNull(fDocumentProvider); + fFileValueMap= new HashMap(5); + fBufferValueMap= new HashMap(5); + } + + public TextBuffer acquire(IFile file) throws CoreException { + FileEditorInput input= new FileEditorInput(file); + + Value value= (Value)fFileValueMap.get(input); + if (value != null) { + value.references++; + return value.buffer; + } + + fDocumentProvider.connect(input); + IDocument document= fDocumentProvider.getDocument(input); + IAnnotationModel annotationModel= fDocumentProvider.getAnnotationModel(input); + annotationModel.connect(document); + value= new Value(new TextBuffer(document), input, document, annotationModel); + fFileValueMap.put(input, value); + fBufferValueMap.put(value.buffer, value); + value.references++; + return value.buffer; + } + + public void release(TextBuffer buffer) { + final Value value= (Value)fBufferValueMap.get(buffer); + if (value == null) + return; + + value.references--; + if (value.references == 0) { + buffer.release(); + value.annotationModel.disconnect(value.document); + fDocumentProvider.disconnect(value.input); + fFileValueMap.remove(value.input); + fBufferValueMap.remove(buffer); + } + } + + public void commitChanges(TextBuffer buffer, boolean force, IProgressMonitor pm) throws CoreException { + final Value value= (Value)fBufferValueMap.get(buffer); + if (value == null) + return; + + boolean save= force || fDocumentProvider.mustSaveDocument(value.input); + if (save) { + IWorkspaceRunnable action= new IWorkspaceRunnable() { + public void run(IProgressMonitor pm) throws CoreException { + fDocumentProvider.aboutToChange(value.input); + fDocumentProvider.saveDocument(pm, value.input, value.document, true); + } + }; + try { + ResourcesPlugin.getWorkspace().run(action, pm); + } finally { + fDocumentProvider.changed(value.input); + } + } + } + + public TextBuffer create(IFile file) throws CoreException { + FileEditorInput input= new FileEditorInput(file); + IDocument document= fDocumentProvider.getDocument(input); + if (document != null) { + return new TextBuffer(new Document(document.get())); + } else { + return createFromFile(file); + } + } + + private TextBuffer createFromFile(IFile file) throws CoreException { + IDocument document; + InputStreamReader in= null; + try { + document= new Document(); + in= new InputStreamReader(new BufferedInputStream(file.getContents())); + StringBuffer buffer= new StringBuffer(); + char[] readBuffer= new char[2048]; + int n= in.read(readBuffer); + while (n > 0) { + buffer.append(readBuffer, 0, n); + n= in.read(readBuffer); + } + document.set(buffer.toString()); + return new TextBuffer(document); + } catch (IOException x) { + IStatus s= new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, CStatusConstants.INTERNAL_ERROR, x.getMessage(), x); + throw new CoreException(s); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException x) { + } + } + } + } + + public TextBuffer create(String content) throws CoreException { + return new TextBuffer(new Document(content)); + } + + public void save(TextBuffer buffer, IProgressMonitor pm) throws CoreException { + Value value= (Value)fBufferValueMap.get(buffer); + if (value == null) + throwNotManaged(); + fDocumentProvider.saveDocument(pm, value.input, value.document, true); + } + + public void aboutToChange(TextBuffer buffer) throws CoreException { + Value value= (Value)fBufferValueMap.get(buffer); + if (value == null) + throwNotManaged(); + fDocumentProvider.aboutToChange(value.input); + } + + public void changed(TextBuffer buffer) throws CoreException { + Value value= (Value)fBufferValueMap.get(buffer); + if (value == null) + throwNotManaged(); + fDocumentProvider.changed(value.input); + } + + private void throwNotManaged() throws CoreException { + IStatus s= new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, + CStatusConstants.INTERNAL_ERROR, "TextBufferFactory.bufferNotManaged", null); //$NON-NLS-1$ + throw new CoreException(s); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEdit.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEdit.java new file mode 100644 index 00000000000..18123d16e3b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEdit.java @@ -0,0 +1,106 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; + +/** + * A text edit describes an elementary text manipulation operation. Text edits + * are executed by adding them to a TextBufferEditor and then + * calling perform on the TextBufferEditor. + *

+ * After a TextEdit has been added to a TextBufferEditor + * the method connect is sent to the text edit. A TextEdit + * is allowed to do some adjustments of the text range it is going to manipulate while inside + * the hook connect. + * + * @see TextBufferEditor + */ +public abstract class TextEdit { + + // index that determines the insertion order into a text buffer + /* package */ int index; + /* package */ boolean isSynthetic; + + /** + * Connects this text edit to the given TextBufferEditor. A text edit + * must not keep a reference to the passed text buffer editor. It is guaranteed that + * the buffer passed to perform is equal to the buffer managed by + * the given text buffer editor. But they don't have to be identical. + *

+ * Note that this method should only be called by a + * TextBufferEditor. + *

+ * This default implementation does nothing. Subclasses may override + * if needed. + * + * @param editor the text buffer editor this text edit has been added to + */ + public void connect(TextBufferEditor editor) throws CoreException { + // does nothing + } + + /** + * Returns the TextRange that this text edit is going to + * manipulate. If this method is called before the TextEdit + * has been added to a TextBufferEditor it may return + * null or TextRange.UNDEFINED to indicate this situation. + * + * @return the TextRanges this TextEdit is going + * to manipulate + */ + public abstract TextRange getTextRange(); + + /** + * Performs the text edit. Note that this method should only be called + * by a TextBufferEditor. + * + * @param buffer the actual buffer to manipulate + * @return a text edit that can undo this text edit + */ + public abstract TextEdit perform(TextBuffer buffer) throws CoreException; + + /** + * This method gets called after all TextEdits added to a text buffer + * editor are executed. Implementors of this method can do some clean-up or can + * release allocated resources that are now longer needed. + *

+ * This default implementation does nothing. + */ + public void performed() { + // do nothing + } + + /** + * Creates and returns a copy of this object. The copy method should + * be implemented in a way so that the copy can be added to a different + * TextBufferEditor without causing any harm to the object + * from which the copy has been created. + * + * @return a copy of this object. + */ + public abstract TextEdit copy() throws CoreException; + + /** + * Returns the element modified by this text edit. The method + * may return null if the modification isn't related to a + * element or if the content of the modified text buffer doesn't + * follow any syntax. + *

+ * This default implementation returns null + * + * @return the element modified by this text edit + */ + public Object getModifiedElement() { + return null; + } + + /** @deprecated reimplement getModifiedElement */ + public final Object getModifiedLanguageElement() { + return null; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNode.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNode.java new file mode 100644 index 00000000000..6e489853898 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNode.java @@ -0,0 +1,496 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.util.Assert; + + +/** + * A helper class to arrange TextEdits into a tree to optimize their + * execution. + */ +/* package */ abstract class TextEditNode { + + /* package */ TextEditNode fParent; + /* package */ List fChildren; + /* package */ TextEdit fEdit; + + /* package */ static class DefaultNode extends TextEditNode { + public DefaultNode(TextEdit edit) { + super(edit); + } + } + + /* package */ static class RootNode extends TextEditNode { + private int fUndoIndex; + public RootNode(int length) { + super(new NopTextEdit(new TextRange(0, length))); + fEdit.isSynthetic= true; + } + public boolean covers(TextEditNode node) { + return true; + } + public UndoMemento performDo(TextBuffer buffer, IProgressMonitor pm) throws CoreException { + DoRangeUpdater updater= new DoRangeUpdater(); + UndoMemento undo= new UndoMemento(TextBufferEditor.UNDO); + try { + buffer.registerUpdater(updater); + performDo(buffer, updater, undo, pm); + } finally { + buffer.unregisterUpdater(updater); + updater.setActiveNode(null); + } + return undo; + } + public UndoMemento performUndo(TextBuffer buffer, IProgressMonitor pm) throws CoreException { + UndoRangeUpdater updater= new UndoRangeUpdater(this); + UndoMemento undo= new UndoMemento(TextBufferEditor.REDO); + try { + buffer.registerUpdater(updater); + performUndo(buffer, updater, undo, pm); + } finally { + buffer.unregisterUpdater(updater); + updater.setActiveNode(null); + } + return undo; + } + + protected void setUndoIndex(int index) { + fUndoIndex= index; + } + + protected int getUndoIndex() { + return fUndoIndex; + } + } + + /* package */ abstract static class AbstractMoveNode extends TextEditNode { + private int state; + + private int fTargetIndex; + private int fSourceIndex; + + private List fAffectedChildren; + + public AbstractMoveNode(TextEdit edit) { + super(edit); + reset(); + } + protected abstract TextRange getSourceRange(); + protected abstract TextRange getTargetRange(); + protected abstract boolean isUpMove(); + protected boolean isDownMove() { + return !isUpMove(); + } + public boolean isMove() { + return true; + } + protected void checkRange(DocumentEvent event) { + TextRange range= getChildRange(); + int eventOffset= event.getOffset(); + int eventLength= event.getLength(); + int eventEnd = eventOffset + eventLength - 1; + // "Edit changes text that lies outside its defined range" + Assert.isTrue(range.fOffset <= eventOffset && eventEnd <= range.getInclusiveEnd()); + } + protected boolean activeNodeChanged(int delta) { + TextRange targetRange= getTargetRange(); + TextRange sourceRange= getSourceRange(); + switch (state) { + case 0: // the move delete + init(); + Assert.isTrue(Math.abs(delta) == sourceRange.fLength); + if (isUpMove()) { + updateOffset(fAffectedChildren, delta); + targetRange.fOffset+= delta; + } + sourceRange.fLength= 0; + state= 1; + break; + case 1: + TextEditNode target= (TextEditNode)fParent.fChildren.get(fTargetIndex); + TextEditNode source= (TextEditNode)fParent.fChildren.get(fSourceIndex); + updateOffset(source.fChildren, targetRange.fOffset - sourceRange.fOffset); + target.fChildren= source.fChildren; + if (target.fChildren != null) { + for (Iterator iter= target.fChildren.iterator(); iter.hasNext();) { + ((TextEditNode)iter.next()).fParent= target; + } + } + source.fChildren= null; + if (isDownMove()) { + updateOffset(fAffectedChildren, delta); + sourceRange.fOffset+= delta; + } + targetRange.fLength= delta; + reset(); + break; + } + return true; + } + private static void updateOffset(List nodes, int delta) { + if (nodes == null) + return; + for (int i= nodes.size() - 1; i >= 0; i--) { + TextEditNode node= (TextEditNode)nodes.get(i); + TextRange range= node.getTextRange(); + range.fOffset+= delta; + updateOffset(node.fChildren, delta); + } + } + private void init() { + TextRange source= getSourceRange(); + TextRange target= getTargetRange(); + List children= fParent.fChildren; + for (int i= children.size() - 1; i >= 0; i--) { + TextEditNode child= (TextEditNode)children.get(i); + TextRange range= child.fEdit.getTextRange(); + if (range == source) + fSourceIndex= i; + else if (range == target) + fTargetIndex= i; + } + int start= Math.min(fTargetIndex, fSourceIndex); + int end= Math.max(fTargetIndex, fSourceIndex); + fAffectedChildren= new ArrayList(3); + for (int i= start + 1; i < end; i++) { + fAffectedChildren.add(children.get(i)); + } + } + private void reset() { + state= 0; + fSourceIndex= -1; + fTargetIndex= -1; + } + } + + /* package */ static class MoveNode extends AbstractMoveNode { + public MoveNode(TextEdit edit) { + super(edit); + } + protected TextRange getChildRange() { + return ((MoveTextEdit)fEdit).getChildRange(); + } + protected TextRange getSourceRange() { + return ((MoveTextEdit)fEdit).getSourceRange(); + } + protected TextRange getTargetRange() { + return ((MoveTextEdit)fEdit).getTargetRange(); + } + protected boolean isUpMove() { + return ((MoveTextEdit)fEdit).isUpMove(); + } + public boolean isMovePartner(TextEditNode other) { + if (!(other instanceof TargetMarkNode)) + return false; + return fEdit == ((MoveTextEdit.TargetMark)other.fEdit).getMoveTextEdit(); + } + public boolean covers(TextEditNode node) { + if (node instanceof TargetMarkNode) { + MoveTextEdit.TargetMark edit= (MoveTextEdit.TargetMark)node.fEdit; + if (edit.getMoveTextEdit() == fEdit) + return false; + } + return getParentRange().covers(node.getChildRange()); + } + } + + /* package */ static class TargetMarkNode extends AbstractMoveNode { + public TargetMarkNode(TextEdit edit) { + super(edit); + } + protected TextRange getChildRange() { + return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getChildRange(); + } + protected TextRange getSourceRange() { + return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getSourceRange(); + } + protected TextRange getTargetRange() { + return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().getTargetRange(); + } + protected boolean isUpMove() { + return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit().isUpMove(); + } + public boolean isMovePartner(TextEditNode other) { + return ((MoveTextEdit.TargetMark)fEdit).getMoveTextEdit() == other.fEdit; + } + } + + //---- Range updating --------------------------------------------------------------------------- + + private static abstract class RangeUpdater implements IDocumentListener { + protected TextEditNode fActiveNode; + public void documentAboutToBeChanged(DocumentEvent event) { + } + public void setActiveNode(TextEditNode node) { + fActiveNode= node; + } + public void updateParents(int delta) { + TextEditNode node= fActiveNode.fParent; + while (node != null) { + node.childNodeChanged(delta); + node= node.fParent; + } + } + public static int getDelta(DocumentEvent event) { + return (event.getText() == null ? 0 : event.getText().length()) - event.getLength(); + } + } + private static class DoRangeUpdater extends RangeUpdater { + private List fProcessedNodes= new ArrayList(10); + public void setActiveNode(TextEditNode node) { + if (fActiveNode != null) + fProcessedNodes.add(fActiveNode); + super.setActiveNode(node); + } + public void documentChanged(DocumentEvent event) { + fActiveNode.checkRange(event); + int delta= getDelta(event); + if (!fActiveNode.activeNodeChanged(delta)) { + for (Iterator iter= fProcessedNodes.iterator(); iter.hasNext();) { + ((TextEditNode)iter.next()).previousNodeChanged(delta); + } + } + updateParents(delta); + } + } + private static class UndoRangeUpdater extends RangeUpdater { + private RootNode fRootNode; + public UndoRangeUpdater(RootNode root) { + fRootNode= root; + } + public void setActiveNode(TextEditNode node) { + super.setActiveNode(node); + } + public void documentChanged(DocumentEvent event) { + fActiveNode.checkRange(event); + int delta= getDelta(event); + if (!fActiveNode.activeNodeChanged(delta)) { + int start= fRootNode.getUndoIndex() + 1; + List children= fRootNode.fChildren; + int size= children != null ? children.size() : 0; + for (int i= start; i < size; i++) { + updateUndo((TextEditNode)children.get(i), delta); + } + } + updateParents(delta); + } + private void updateUndo(TextEditNode node, int delta) { + node.previousNodeChanged(delta); + List children= node.fChildren; + int size= children != null ? children.size() : 0; + for (int i= 0; i < size; i++) { + updateUndo((TextEditNode)children.get(i), delta); + } + } + } + + //---- Creating instances --------------------------------------------------------------------------- + + static TextEditNode create(TextEdit edit) { + if (edit instanceof MoveTextEdit) + return new MoveNode(edit); + if (edit instanceof MoveTextEdit.TargetMark) + return new TargetMarkNode(edit); + return new DefaultNode(edit); + } + + static RootNode createRoot(int length) { + return new RootNode(length); + } + + private TextEditNode(TextEdit edit) { + fEdit= edit; + } + + //---- Adding children --------------------------------------------------------------------------- + + protected void add(TextEditNode node) { + if (fChildren == null) { + fChildren= new ArrayList(1); + node.fParent= this; + fChildren.add(node); + return; + } + // Optimize using binary search + for (Iterator iter= fChildren.iterator(); iter.hasNext();) { + TextEditNode child= (TextEditNode)iter.next(); + if (child.covers(node)) { + child.add(node); + return; + } + } + for (int i= 0; i < fChildren.size(); ) { + TextEditNode child= (TextEditNode)fChildren.get(i); + if (node.covers(child)) { + fChildren.remove(i); + node.add(child); + } else { + i++; + } + } + node.fParent= this; + fChildren.add(node); + } + + public boolean covers(TextEditNode node) { + return false; + } + + //---- Accessing -------------------------------------------------------------------------------------- + + protected RootNode getRoot() { + TextEditNode candidate= this; + while(candidate.fParent != null) + candidate= candidate.fParent; + return (RootNode)candidate; + } + + //---- Query interface -------------------------------------------------------------------------------- + + protected boolean isSynthetic() { + return fEdit.isSynthetic; + } + + public boolean isMove() { + return false; + } + + //---- Accessing Ranges ------------------------------------------------------------------------------ + + protected void checkRange(DocumentEvent event) { + TextRange range= getTextRange(); + int eventOffset= event.getOffset(); + int eventLength= event.getLength(); + int eventEnd = eventOffset + eventLength - 1; + // "Edit changes text that lies outside its defined range" + Assert.isTrue(range.fOffset <= eventOffset && eventEnd <= range.getInclusiveEnd()); + } + + protected TextRange getTextRange() { + return fEdit.getTextRange(); + } + + protected TextRange getChildRange() { + return getTextRange(); + } + + protected TextRange getParentRange() { + return getTextRange(); + } + + public boolean validate(int bufferLength) { + if (fChildren == null) + return true; + // Only Moves and Nops can be parents + if (!(fEdit instanceof MoveTextEdit || fEdit instanceof NopTextEdit)) + return false; + TextRange lastRange= null; + for (Iterator iter= fChildren.iterator(); iter.hasNext(); ) { + TextEditNode node= (TextEditNode)iter.next(); + if (!node.validate(bufferLength)) + return false; + TextRange range= node.fEdit.getTextRange(); + if (!range.isValid() || range.fOffset + range.fLength > bufferLength) + return false; + if (lastRange != null && !(range.isInsertionPointAt(lastRange.fOffset) || range.liesBehind(lastRange))) + return false; + lastRange= range; + } + return true; + } + + //---- Updating ---------------------------------------------------------------------------------------- + + protected boolean activeNodeChanged(int delta) { + TextRange range= getTextRange(); + range.fLength+= delta; + // we didn't adjust any processed nodes. + return false; + } + + protected void previousNodeChanged(int delta) { + TextRange range= getTextRange(); + range.fOffset+= delta; + } + + protected void childNodeChanged(int delta) { + getTextRange().fLength+= delta; + } + + //---- Do it --------------------------------------------------------------------------------------------- + + protected void performDo(TextBuffer buffer, RangeUpdater updater, UndoMemento undo, IProgressMonitor pm) throws CoreException { + int size= fChildren != null ? fChildren.size() : 0; + for (int i= size - 1; i >= 0; i--) { + TextEditNode child= (TextEditNode)fChildren.get(i); + child.performDo(buffer, updater, undo, pm); + } + updater.setActiveNode(this); + if (isSynthetic()) + fEdit.perform(buffer); + else + undo.add(fEdit.perform(buffer)); + pm.worked(1); + } + + public void performedDo() { + int size= fChildren != null ? fChildren.size() : 0; + for (int i= size - 1; i >= 0; i--) { + TextEditNode child= (TextEditNode)fChildren.get(i); + child.performedDo(); + } + fEdit.performed(); + } + + //---- Undo it ------------------------------------------------------------------------------------------- + + protected void performUndo(TextBuffer buffer, RangeUpdater updater, UndoMemento undo, IProgressMonitor pm) throws CoreException { + int size= fChildren != null ? fChildren.size() : 0; + for (int i= 0; i < size; i++) { + setUndoIndex(i); + TextEditNode child= (TextEditNode)fChildren.get(i); + child.performUndo(buffer, updater, undo, pm); + } + updater.setActiveNode(this); + if (isSynthetic()) + fEdit.perform(buffer); + else + undo.add(fEdit.perform(buffer)); + pm.worked(1); + } + + protected void setUndoIndex(int index) { + } + + public void performedUndo() { + int size= fChildren != null ? fChildren.size() : 0; + for (int i= 0; i < size; i++) { + TextEditNode child= (TextEditNode)fChildren.get(i); + child.performedUndo(); + } + fEdit.performed(); + } + +// protected void createUndoList(List list) { +// int size= fChildren != null ? fChildren.size() : 0; +// for (int i= 0; i < size; i++) { +// TextEditNode child= (TextEditNode)fChildren.get(i); +// child.createUndoList(list); +// } +// list.add(this); +// } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNodeComparator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNodeComparator.java new file mode 100644 index 00000000000..33e527f5787 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextEditNodeComparator.java @@ -0,0 +1,48 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Comparator; + +/** + * A special comparator to comapre TextRanges. + */ +class TextEditNodeComparator implements Comparator { + public int compare(Object o1, Object o2) { + TextEditNode node1= (TextEditNode)o1; + TextEditNode node2= (TextEditNode)o2; + TextRange pos1= node1.getTextRange(); + TextRange pos2= node2.getTextRange(); + + int offset1= pos1.fOffset; + int offset2= pos2.fOffset; + if (offset1 < offset2) + return -1; + if (offset1 > offset2) + return 1; + + // same offset + int length1= pos1.fLength; + int length2= pos2.fLength; + + // insertion points come before anything else at the same position. + if (length1 == 0 && length2 != 0) + return -1; + if (length1 != 0 && length2 == 0) + return 1; + + // Longer edits come before shorter edits + if (length1 < length2) + return 1; + if (length1 > length2) + return -1; + + if (node1.fEdit.index < node2.fEdit.index) + return -1; + return 1; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextManipulationMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextManipulationMessages.java new file mode 100644 index 00000000000..989fdd9e650 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextManipulationMessages.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/******************************************************************************* + * Copyright (c) 2002 International Business Machines Corp. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class TextManipulationMessages { + + private static final String BUNDLE_NAME= "org.eclipse.jdt.internal.corext.textmanipulation.Messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE= ResourceBundle.getBundle(BUNDLE_NAME); + + private TextManipulationMessages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + public static String getFormattedString(String key, Object arg) { + return getFormattedString(key, new Object[] { arg }); + } + + public static String getFormattedString(String key, Object[] args) { + return MessageFormat.format(getString(key), args); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRange.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRange.java new file mode 100644 index 00000000000..6bff924fc3a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRange.java @@ -0,0 +1,196 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.util.Assert; + + + +public final class TextRange { + + /* package */ int fOffset; + /* package */ int fLength; + + public static final TextRange UNDEFINED= new TextRange((TextRange)null); + + /** + * Creates a insert position with the given offset. + * + * @param offset the position offset, must be >= 0 + */ + public TextRange(int offset) { + this(offset, 0); + } + + /** + * Creates a new range with the given offset and length. + * + * @param offset the position offset, must be >= 0 + * @param length the position length, must be >= 0 + */ + public TextRange(int offset, int length) { + fOffset= offset; + Assert.isTrue(fOffset >= 0); + fLength= length; + Assert.isTrue(fLength >= 0); + } + + /** + * Constructor for the undefined text range. + */ + private TextRange(TextRange dummy) { + fOffset= -1; + fLength= -1; + } + + public static TextRange createFromStartAndLength(int start, int length) { + return new TextRange(start, length); + } + + public static TextRange createFromStartAndInclusiveEnd(int start, int end) { + return new TextRange(start, end - start + 1); + } + + public static TextRange createFromStartAndExclusiveEnd(int start, int end) { + return new TextRange(start, end - start); + } + + /** + * Creates a new range from the given source range. + * + * @range the source range denoting offset and length + */ + public TextRange(ISourceRange range) { + this(range.getOffset(), range.getLength()); + } + + /** + * Returns the offset of this range. + * + * @return the length of this range + */ + public int getOffset() { + return fOffset; + } + + /** + * Returns the length of this range. + * + * @return the length of this range + */ + public int getLength() { + return fLength; + } + + /** + * Returns the inclusive end position of this range. That means that the end position + * denotes the last character of this range. + * + * @return the inclusive end position + */ + public int getInclusiveEnd() { + return fOffset + fLength - 1; + } + + /** + * Returns the exclusive end position of this range. That means that the end position + * denotes the first character after this range. + * + * @return the exclusive end position + */ + public int getExclusiveEnd() { + return fOffset + fLength; + } + + /** + * Creates a copy of this TextRange. + * + * @return a copy of this TextRange + */ + public TextRange copy() { + if (isUndefined()) + return this; + return new TextRange(fOffset, fLength); + } + + /** + * Returns true if this text range is the UNDEFINED + * text range. Otherwise false is returned. + */ + public boolean isUndefined() { + return UNDEFINED == this; + } + + /** + * Checks if this TextRange is valid. For valid text range the following + * expression evaluates to true: + *

+	 * 	getOffset() >= 0 && getLength() >= 0
+	 * 
+ * + * @return true if this text range is a valid range. Otherwise + * false + */ + public boolean isValid() { + return fOffset >= 0 && fLength >= 0; + } + + /* package */ boolean isInsertionPoint() { + return fLength == 0; + } + + /* package */ boolean equals(TextRange range) { + return fOffset == range.fOffset && fLength == range.fLength; + } + + /* package */ boolean isEqualInsertionPoint(TextRange range) { + return fLength == 0 && range.fLength == 0 && fOffset == range.fOffset; + } + + /* package */ boolean liesBehind(TextRange range) { + return fOffset >= range.fOffset + range.fLength; + } + + /* package */ boolean isInsertionPointAt(int o) { + return fOffset == o && fLength == 0; + } + + /* package */ boolean covers(TextRange other) { + if (fLength == 0) { // an insertion point can't cover anything + return false; + } else if (other.fLength == 0) { + int otherOffset= other.fOffset; + return fOffset < otherOffset && otherOffset < fOffset + fLength; + } else { + int otherOffset= other.fOffset; + return fOffset <= otherOffset && otherOffset + other.fLength <= fOffset + fLength; + } + } + /* non Java-doc + * @see Object#toString() + */ + public String toString() { + StringBuffer buffer= new StringBuffer(); + buffer.append(TextManipulationMessages.getString("TextRange.offset")); //$NON-NLS-1$ + buffer.append(fOffset); + buffer.append(TextManipulationMessages.getString("TextRange.length")); //$NON-NLS-1$ + buffer.append(fLength); + return buffer.toString(); + } + + public boolean equals(Object obj) { + if (! (obj instanceof TextRange)) + return false; + TextRange other= (TextRange)obj; + return fOffset == other.getOffset() && fLength == other.getLength(); + } + + public int hashCode() { + return fOffset ^ fLength; + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRegion.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRegion.java new file mode 100644 index 00000000000..b6e06dd88eb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextRegion.java @@ -0,0 +1,37 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * A text region describes a certain range in an ITextBuffer. A region is defined by + * its offset into the text buffer and its length. + *

+ * A region is considered a value object. Its offset or length do not change over time.

+ *

+ * NOTE: This class/interface is part of an interim API that is still under development + * and expected to change significantly before reaching stability. It is being made available at + * this early stage to solicit feedback from pioneering adopters on the understanding that any + * code that uses this API will almost certainly be broken (repeatedly) as the API evolves.

+ */ + +// This class avoids contamination of clients with wrong imports. + +public abstract class TextRegion { + + /** + * Returns the offset of the region. + * + * @return the offset of the region + */ + public abstract int getOffset(); + /** + * Returns the length of the region. + * + * @return the length of the region + */ + public abstract int getLength(); + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextUtil.java new file mode 100644 index 00000000000..0cefd11a18f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/TextUtil.java @@ -0,0 +1,147 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.util.Assert; + + +public class TextUtil { + + /** + * Returns the length of the string desribed by start and + * end. + * + * @param start the start position. The position is inclusive + * @param end the end position. The position is inclusive + * @return the length of the string desribed by start and + * end + */ + public static int getLength(int start, int end) { + return end - start + 1; + } + + /** + * Returns the indent of the given line. + * @param line the text line + * @param tabWidth the width of the '\t' character. + */ + public static int getIndent(String line, int tabWidth) { + int result= 0; + int blanks= 0; + int size= line.length(); + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + switch (c) { + case '\t': + result++; + blanks= 0; + break; + case ' ': + blanks++; + if (blanks == tabWidth) { + result++; + blanks= 0; + } + break; + default: + return result; + } + } + return result; + } + + /** + * Removes the given number of idents from the line and returns a new + * copy of the line. Asserts that the given line has the requested + * number of indents. + */ + public static String removeIndent(int numberOfIndents, String line, int tabWidth) { + if (numberOfIndents <= 0) + return new String(line); + + int start= 0; + int indents= 0; + int blanks= 0; + int size= line.length(); + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + switch (c) { + case '\t': + indents++; + blanks= 0; + break; + case ' ': + blanks++; + if (blanks == tabWidth) { + indents++; + blanks= 0; + } + break; + default: + Assert.isTrue(false, "Line does not have requested number of indents"); //$NON-NLS-1$ + } + if (indents == numberOfIndents) { + start= i + 1; + break; + } + } + if (start == size) + return ""; //$NON-NLS-1$ + else + return line.substring(start); + } + + /** + * Removes any leading indents from the given string. + */ + public static String removeLeadingIndents(String line, int tabWidth) { + int indents= getIndent(line, tabWidth); + return removeIndent(indents, line, tabWidth); + } + + /** + * Creates a string that consists of the given number of tab characters. + */ + public static String createIndentString(int indent) { + StringBuffer result= new StringBuffer(); + for (int i= 0; i < indent; i++) { + result.append('\t'); + } + return result.toString(); + } + + /** + * Removes any leading white spaces from the given string. + * The method returns a new string. + */ + public static String removeLeadingWhiteSpaces(String line) { + int size= line.length(); + int start= 0; + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + if (c != '\t' && c != ' ') { + start= i; + break; + } + } + return line.substring(start); + } + + /** + * Returns true if the given string consists only of + * white spaces (e.g. space and '\t'). If the string is empty, + * true is returned. + */ + public static boolean containsOnlyWhiteSpaces(String line) { + int size= line.length(); + for (int i= 0; i < size; i++) { + char c= line.charAt(i); + if (c != '\t' && c != ' ') + return false; + } + return true; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/UndoMemento.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/UndoMemento.java new file mode 100644 index 00000000000..3af1ebf7473 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/textmanipulation/UndoMemento.java @@ -0,0 +1,29 @@ +package org.eclipse.cdt.internal.corext.textmanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * This class encapsulates the reverse change of a number of TextEdits + * executed on a TextBufferEditor + */ +public final class UndoMemento { + + /* package */ int fMode; + /* package */ List fEdits; + + /* package */ UndoMemento(int mode) { + fMode= mode; + fEdits= new ArrayList(10); + } + + /* package */ void add(TextEdit edit) { + fEdits.add(edit); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java new file mode 100644 index 00000000000..8857e7802ba --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java @@ -0,0 +1,238 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.IBinaryContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IParent; + +/** + * A base content provider for C elements. It provides access to the + * C element hierarchy without listening to changes in the C model. + * Use this class when you want to present the C elements + * in a modal dialog or wizard. + *

+ * The following C element hierarchy is surfaced by this content provider: + *

+ *

+C model (ICModel)
+   C project (ICProject)
+      C Folder (ICFolder)
+      C File (ICFile)
+      Translation unit (ITranslationUnit)
+      Binary file (IBinary)
+      Archive file (IArchive)
+ * 
+ */ +public class BaseCElementContentProvider implements ITreeContentProvider { + + protected static final Object[] NO_CHILDREN= new Object[0]; + + protected boolean fProvideMembers= false; + protected boolean fProvideWorkingCopy= false; + + public BaseCElementContentProvider() { + } + + public BaseCElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) { + fProvideMembers= provideMembers; + //fProvideWorkingCopy= provideWorkingCopy; + } + + /** + * Returns whether the members are provided when asking + * for a TU's or ClassFile's children. + */ + public boolean getProvideMembers() { + return fProvideMembers; + } + + /** + * Returns whether the members are provided when asking + * for a TU's or ClassFile's children. + */ + public void setProvideMembers(boolean b) { + fProvideMembers= b; + } + + /** + * Sets whether the members are provided from + * a working copy of a compilation unit + */ + public void setProvideWorkingCopy(boolean b) { + //fProvideWorkingCopy= b; + } + + /** + * Returns whether the members are provided + * from a working copy a compilation unit. + */ + public boolean getProvideWorkingCopy() { + return fProvideWorkingCopy; + } + + /* (non-Cdoc) + * Method declared on IStructuredContentProvider. + */ + public Object[] getElements(Object parent) { + return getChildren(parent); + } + + /* (non-Cdoc) + * Method declared on IContentProvider. + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + /* (non-Cdoc) + * Method declared on IContentProvider. + */ + public void dispose() { + } + + /* (non-Cdoc) + * Method declared on ITreeContentProvider. + */ + public Object[] getChildren(Object element) { + if (element instanceof ICElement) { + ICElement celement = (ICElement)element; + if (celement.getElementType() == ICElement.C_FILE) { + if (fProvideMembers) { + return ((IParent)element).getChildren(); + } + } else if (celement instanceof IParent) { + if (celement instanceof ICProject ) { + ICElement[] children = ((IParent)celement).getChildren(); + ArrayList list = new ArrayList(children.length); + for( int i = 0; i < children.length; i++ ) { + // Note, here we are using getBinaries() and getArchives() + // instead. Those methods are async and they start threads + // in the background. This will not freeze the viewer + // But we should note that the user should add itself to + // the listener of the Core Model so when the threads discover + // new binaries/archives to get notification. + if (children[i] instanceof IArchiveContainer) { + IArchiveContainer carchive = (IArchiveContainer)children[i]; + if (carchive.getArchives().length == 0) { + continue; + } + } else if (children[i] instanceof IBinaryContainer) { + IBinaryContainer cbin = (IBinaryContainer)children[i]; + if (cbin.getBinaries().length == 0) { + continue; + } + } + list.add(children[i]); + } + return list.toArray(); + } else + return (Object[])((IParent)celement).getChildren(); + } + } + return getResources(element); + } + + /* (non-Cdoc) + * + * @see ITreeContentProvider + */ + public boolean hasChildren(Object element) { + if (fProvideMembers) { + if (element instanceof ICFile) { + ICFile cfile = (ICFile)element; + // assume TUs and binary files are never empty + if (cfile.isBinary() || cfile.isTranslationUnit() || cfile.isArchive()) { + return true; + } + } + } else { + // don't allow to drill down into a compilation unit or class file + if (element instanceof ICFile || element instanceof IFile) + return false; + } + + if (element instanceof ICProject) { + ICProject cp= (ICProject)element; + if (!cp.getProject().isOpen()) { + return false; + } + } + + if (element instanceof IParent) { + // when we have C children return true, else we fetch all the children + return ((IParent)element).hasChildren(); + } + Object[] children= getChildren(element); + return (children != null) && children.length > 0; + } + + /* (non-Cdoc) + * Method declared on ITreeContentProvider. + */ + public Object getParent(Object element) { + //if (!exists(element)) + // return null; + if (element instanceof ICElement) { + return ((ICElement)element).getParent(); + } + if (element instanceof IResource) { + return ((IResource)element).getParent(); + } + return null; + } + + private Object[] getResources(Object resource) { + try { + if (resource instanceof IContainer) { + Object[] members= ((IContainer)resource).members(); + List nonCResources= new ArrayList(); + for (int i= 0; i < members.length; i++) { + Object o= members[i]; + nonCResources.add(o); + } + return nonCResources.toArray(); + } + } catch(CoreException e) { + } + return NO_CHILDREN; + } +/* + protected boolean isBuildPathChange(ICElementDelta delta) { + int flags= delta.getFlags(); + return (delta.getKind() == ICElementDelta.CHANGED && + ((flags & ICElementDelta.F_ADDED_TO_CLASSPATH) != 0) || + ((flags & ICElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || + ((flags & ICElementDelta.F_CLASSPATH_REORDER) != 0)); + } +*/ + + + protected boolean exists(Object element) { + if (element == null) { + return false; + } + if (element instanceof IResource) { + return ((IResource)element).exists(); + } + if (element instanceof ICElement) { + return ((ICElement)element).exists(); + } + return true; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BinaryPropertySource.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BinaryPropertySource.java new file mode 100644 index 00000000000..1cd706ebacc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BinaryPropertySource.java @@ -0,0 +1,151 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.FilePropertySource; +import org.eclipse.ui.views.properties.PropertyDescriptor; + +import org.eclipse.cdt.core.model.IBinary; + +public class BinaryPropertySource extends FilePropertySource { + + private final static String ELF_CPU= "CElementProperties.elf_cpu"; + private final static String ELF_TEXT= "CElementProperties.elf_text"; + private final static String ELF_DATA= "CElementProperties.elf_data"; + private final static String ELF_BSS= "CElementProperties.elf_bss"; + private final static String ELF_TYPE= "CElementProperties.elf_type"; + private final static String ELF_HAS_DEBUG= "CElementProperties.elf_has_debug"; + private final static String ELF_SONAME= "CElementProperties.elf_soname"; + private final static String ELF_NEEDED= "CElementProperties.elf_needed"; + + private IBinary binary; + + // Property Descriptors + static private IPropertyDescriptor[] fgPropertyDescriptors; + + /** + * Get a PropertyDescriptor that defines the binary properties of an Elf + * @return the PropertyDescriptor + */ + private static IPropertyDescriptor[] getInitialPropertyDescriptor() { + // cpu name + String cpuName= CPlugin.getResourceString(ELF_CPU); + PropertyDescriptor cpuDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_CPU, cpuName); + cpuDescriptor.setAlwaysIncompatible(true); + + // elf text + String textName = CPlugin.getResourceString(ELF_TEXT); + PropertyDescriptor textDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_TEXT, textName); + textDescriptor.setAlwaysIncompatible(true); + + // elf data + String dataName = CPlugin.getResourceString(ELF_DATA); + PropertyDescriptor dataDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_DATA, dataName); + dataDescriptor.setAlwaysIncompatible(true); + + // elf bss + String bssName = CPlugin.getResourceString(ELF_BSS); + PropertyDescriptor bssDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_BSS, bssName); + bssDescriptor.setAlwaysIncompatible(true); + + // elf type + String typeName = CPlugin.getResourceString(ELF_TYPE); + PropertyDescriptor typeDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_TYPE, typeName); + bssDescriptor.setAlwaysIncompatible(true); + + // elf needed + String neededName = CPlugin.getResourceString(ELF_NEEDED); + PropertyDescriptor neededDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_NEEDED, neededName); + bssDescriptor.setAlwaysIncompatible(true); + + // elf soname + String sonameName = CPlugin.getResourceString(ELF_SONAME); + PropertyDescriptor sonameDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_SONAME, sonameName); + bssDescriptor.setAlwaysIncompatible(true); + + // elf debug + String debugName = CPlugin.getResourceString(ELF_HAS_DEBUG); + PropertyDescriptor debugDescriptor= new PropertyDescriptor(ICElementPropertyConstants.P_ELF_HAS_DEBUG, debugName); + bssDescriptor.setAlwaysIncompatible(true); + + return new IPropertyDescriptor[] { cpuDescriptor, textDescriptor, dataDescriptor, + bssDescriptor, typeDescriptor, sonameDescriptor, debugDescriptor, neededDescriptor }; + } + + public BinaryPropertySource(IBinary bin) { + super(bin.getFile()); + this.binary= bin; + } + + /** + * @see IPropertySource#getPropertyDescriptors + */ + public IPropertyDescriptor[] getPropertyDescriptors() { + if (fgPropertyDescriptors == null) + initializeBinaryDescriptors(); + return fgPropertyDescriptors; + } + + /** + * @see IPropertySource#getPropertyValue + */ + public Object getPropertyValue(Object name) { + if (element != null) { + Object returnValue = super.getPropertyValue(name); + + if(returnValue != null) + return returnValue; + } + + if (name.equals(ICElementPropertyConstants.P_ELF_CPU)) { + return binary.getCPU(); + } else if (name.equals(ICElementPropertyConstants.P_ELF_TEXT)) { + return Long.toString(binary.getText()); + } else if (name.equals(ICElementPropertyConstants.P_ELF_DATA)) { + return Long.toString(binary.getData()); + } else if (name.equals(ICElementPropertyConstants.P_ELF_BSS)) { + return Long.toString(binary.getBSS()); + } else if (name.equals(ICElementPropertyConstants.P_ELF_SONAME)) { + return binary.getSoname(); + } else if (name.equals(ICElementPropertyConstants.P_ELF_HAS_DEBUG)) { + if (binary.hasDebug()) { + return "true";//$NON-NLS-1$ + } else { + return "false";//$NON-NLS-1$ + } + } else if (name.equals(ICElementPropertyConstants.P_ELF_NEEDED)) { + String[] needed = binary.getNeededSharedLibs(); + String need = ""; + for (int i = 0; i < needed.length; i++) { + need += " " + needed[i]; + } + return need.trim(); + } else if (name.equals(ICElementPropertyConstants.P_ELF_TYPE)) { + if (binary.isObject()) { + return "object"; + } else if (binary.isExecutable()) { + return "executable"; + } else if (binary.isSharedLib()) { + return "shared library"; + } + } + return null; + } + + /** + * Return the Property Descriptors for the file type. + */ + private void initializeBinaryDescriptors() { + IPropertyDescriptor[] superDescriptors = super.getPropertyDescriptors(); + int superLength = superDescriptors.length; + IPropertyDescriptor[] binDescriptors = getInitialPropertyDescriptor(); + int binLength = binDescriptors.length; + fgPropertyDescriptors = new IPropertyDescriptor[superLength + binLength]; + System.arraycopy(superDescriptors, 0, fgPropertyDescriptors, 0, superLength); + System.arraycopy(binDescriptors, 0, fgPropertyDescriptors, superLength, binLength); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleAction.java new file mode 100644 index 00000000000..e326495b1f7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleAction.java @@ -0,0 +1,55 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import java.util.ResourceBundle; + + +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.TextViewer; + + +import org.eclipse.ui.texteditor.TextEditorAction; + + +public class BuildConsoleAction extends TextEditorAction { + + + private int fOperationCode= -1; + private ITextOperationTarget fOperationTarget; + + + public BuildConsoleAction(ResourceBundle bundle, String prefix, TextViewer viewer, int operationCode) { + super(bundle, prefix, null); + fOperationCode= operationCode; + fOperationTarget= viewer.getTextOperationTarget(); + update(); + } + /** + * @see Action + */ + public void run() { + if (fOperationCode != -1 && fOperationTarget != null) { + fOperationTarget.doOperation(fOperationCode); + } + } + /** + * @see TextEditorAction + */ + public void update() { + + + //boolean wasEnabled= isEnabled(); + boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); + setEnabled(isEnabled); + + + /*if (wasEnabled != isEnabled) { + firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); + }*/ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleView.java new file mode 100644 index 00000000000..16713543a68 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BuildConsoleView.java @@ -0,0 +1,210 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ResourceBundle; + + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; + + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.help.ViewContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.TextEditorAction; + + +import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage; + +/** + * Console view for the desktop. Registered using XML. + */ +public class BuildConsoleView extends ViewPart { + + + private TextViewer fTextViewer; + private ClearConsoleAction fClearOutputAction; + private TextEditorAction fCopyAction; + private TextEditorAction fSelectAllAction; + private Font fFont; + + private IPropertyChangeListener fPropertyChangeListener; + + + public BuildConsoleView() { + super(); + fFont= null; + fPropertyChangeListener= new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fTextViewer != null && event.getProperty().equals(CPluginPreferencePage.PREF_CONSOLE_FONT)) { + initializeWidgetFont(fTextViewer.getTextWidget()); + } + } + }; + IPreferenceStore store= CPlugin.getDefault().getPreferenceStore(); + store.addPropertyChangeListener(fPropertyChangeListener); + } + + private void initializeActions() { + ResourceBundle bundle= CPlugin.getResourceBundle(); + + IActionBars actionBars= getViewSite().getActionBars(); + fClearOutputAction= new ClearConsoleAction(this); + fCopyAction= new BuildConsoleAction(bundle, "Editor.Copy.", fTextViewer, fTextViewer.COPY); + fSelectAllAction= new BuildConsoleAction(bundle, "Editor.SelectAll.", fTextViewer, fTextViewer.SELECT_ALL); + + + actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, fCopyAction); + actionBars.setGlobalActionHandler(ITextEditorActionConstants.SELECT_ALL, fSelectAllAction); + } + + /** + * @see ViewPart#createPartControl + */ + public void createPartControl(Composite parent) { + //fTextViewer= new TextViewer(parent, SWT.V_SCROLL|SWT.H_SCROLL); + fTextViewer= new TextViewer(parent, SWT.V_SCROLL|SWT.H_SCROLL|SWT.WRAP|SWT.MULTI); + fTextViewer.setDocument(CPlugin.getDefault().getConsoleDocument()); + fTextViewer.addTextListener(new ITextListener() { + public void textChanged(TextEvent event) { + revealEndOfDocument(); + } + }); + fTextViewer.setEditable(false); + initializeWidgetFont(fTextViewer.getTextWidget()); + + + initializeActions(); + initializeContextMenu(parent); + initializeToolBar(); + + WorkbenchHelp.setHelp(fTextViewer.getControl(), new ViewContextComputer(this, ICHelpContextIds.CLEAR_CONSOLE_VIEW)); + } + + private void initializeWidgetFont(StyledText styledText) { + IPreferenceStore store= CPlugin.getDefault().getPreferenceStore(); + String prefKey= CPluginPreferencePage.PREF_CONSOLE_FONT; + FontData data= null; + if (store.contains(prefKey) && !store.isDefault(prefKey)) { + data= PreferenceConverter.getFontData(store, prefKey); + } else { + data= PreferenceConverter.getDefaultFontData(store, prefKey); + } + if (data != null) { + Font font= new Font(styledText.getDisplay(), data); + styledText.setFont(font); + + if (fFont != null) + fFont.dispose(); + + fFont= font; + } else { + // if all the preferences failed + styledText.setFont(JFaceResources.getTextFont()); + } + } + + + /** + * @see IWorkbenchPart#setFocus() + */ + public void setFocus() { + } + + /** + * Initializes the context menu + */ + protected void initializeContextMenu(Control parent) { + MenuManager menuMgr= new MenuManager("#PopupMenu"); + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + fillContextMenu(manager); + } + }); + Menu menu= menuMgr.createContextMenu(parent); + parent.setMenu(menu); + } + + /** + * Adds the text manipulation actions to the ConsoleViewer + */ + protected void fillContextMenu(IMenuManager menu) { + fCopyAction.update(); + menu.add(fCopyAction); + menu.add(fSelectAllAction); + menu.add(new Separator()); + menu.add(fClearOutputAction); + } + + /** + * Configures the toolBar. + */ + private void initializeToolBar() { + IActionBars actionBars= getViewSite().getActionBars(); + actionBars.getToolBarManager().add(fClearOutputAction); + actionBars.updateActionBars(); + } + + /** + * Clears the console + */ + void clear() { + //fTextViewer.getDocument().set(""); + CPlugin.getDefault().getConsole().clear(); + } + + /** + * Reveals (makes visible) the end of the current document + */ + protected void revealEndOfDocument() { + IDocument doc= fTextViewer.getDocument(); + int docLength= doc.getLength(); + if (docLength > 0) { + fTextViewer.revealRange(docLength - 1, 1); + StyledText widget= fTextViewer.getTextWidget(); + widget.setCaretOffset(docLength); + } + } + /** + * @see WorkbenchPart#dispose() + */ + public void dispose() { + super.dispose(); + if (fPropertyChangeListener != null) { + IPreferenceStore store= CPlugin.getDefault().getPreferenceStore(); + store.removePropertyChangeListener(fPropertyChangeListener); + fPropertyChangeListener= null; + } + if (fFont != null) { + fFont.dispose(); + fFont= null; + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CCompletionContributorManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CCompletionContributorManager.java new file mode 100644 index 00000000000..ceda1ef6f65 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CCompletionContributorManager.java @@ -0,0 +1,112 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.ui.ICCompletionContributor; +import org.eclipse.cdt.ui.IFunctionSummary; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.Platform; + + +/** + * Manages external plugins that contribute completion and function + * info through the CCompletionContributor extension point + */ + +public class CCompletionContributorManager { + + static private List fCompletionContributors; + static boolean fContributorsLoaded = false; + public static final String CONTRIBUTION_EXTENSION = "CCompletionContributor"; + static private CCompletionContributorManager fInstance; + + + private CCompletionContributorManager() { + // Initialize and scan the extension points + } + + public static CCompletionContributorManager getDefault() { + if(fInstance == null) { + fInstance = new CCompletionContributorManager(); + } + return fInstance; + } + + public static IFunctionSummary getFunctionInfo(String name) { + if(!fContributorsLoaded) + loadExtensions(); + + for (int i= 0; i < fCompletionContributors.size(); i++) { + ICCompletionContributor c = (ICCompletionContributor)fCompletionContributors.get(i); + IFunctionSummary f = c.getFunctionInfo(name); + + if(f != null) + return f; + } + return null; + } + + public static IFunctionSummary[] getMatchingFunctions(String frag) { + if(!fContributorsLoaded) + loadExtensions(); + IFunctionSummary[] fs = null; + + for (int i= 0; i < fCompletionContributors.size(); i++) { + ICCompletionContributor c = (ICCompletionContributor)fCompletionContributors.get(i); + IFunctionSummary[] f = c.getMatchingFunctions(frag); + if(f != null) { + if(fs != null) { + int length = f.length + fs.length; + IFunctionSummary[] ft = new IFunctionSummary[length]; + int j; + for(j = 0; j < fs.length; j++) ft[j] = fs[j]; + for(j = 0; j < f.length; j++) ft[j + fs.length] = f[j]; + fs = ft; + } else { + fs = f; + } + } + + //if(f != null) + //return f; + } + + return fs; + } + + static private void loadExtensions() { + fContributorsLoaded = true; + fCompletionContributors= new ArrayList(2); + + // populate list + IExtensionPoint extensionPoint= Platform.getPluginRegistry().getExtensionPoint(CPlugin.PLUGIN_ID, "CCompletionContributor"); //$NON-NLS-1$ + if (extensionPoint != null) { + IConfigurationElement[] elements= extensionPoint.getConfigurationElements(); + for (int i= 0; i < elements.length; i++) { + if(elements[i].getName().equals("provider")) { + ICCompletionContributor c; + + try { + // Instantiate the classe + c = (ICCompletionContributor)elements[i].createExecutableExtension("class"); + // Initialize + c.initialize(); + // Add to contributor list + fCompletionContributors.add(c); + } catch (CoreException e) { + System.out.println("Unable to instantiate ContributionManager extension"); + } + } + } + } + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CContentProvider.java new file mode 100644 index 00000000000..4814fc49882 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CContentProvider.java @@ -0,0 +1,295 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.CModelException; + +public class CContentProvider extends BaseCElementContentProvider implements ITreeContentProvider, IElementChangedListener { + + protected StructuredViewer fViewer; + protected Object fInput; + + /* (non-Cdoc) + * Method declared on IContentProvider. + */ + public void dispose() { + super.dispose(); + CoreModel.getDefault().removeElementChangedListener(this); + } + + /* (non-Cdoc) + * Method declared on IContentProvider. + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + super.inputChanged(viewer, oldInput, newInput); + + fViewer = (StructuredViewer)viewer; + + if (oldInput == null && newInput != null) { + if (newInput instanceof ICRoot) + CoreModel.getDefault().addElementChangedListener(this); + } else if (oldInput != null && newInput == null) { + CoreModel.getDefault().removeElementChangedListener(this); + } + fInput= newInput; + } + + /** + * Creates a new content provider for C elements. + */ + public CContentProvider() { + } + + /** + * Creates a new content provider for C elements. + */ + public CContentProvider(boolean provideMembers, boolean provideWorkingCopy) { + super(provideMembers, provideWorkingCopy); + } + + /* (non-Cdoc) + * Method declared on IElementChangedListener. + */ + public void elementChanged(final ElementChangedEvent event) { + try { + processDelta(event.getDelta()); + } catch(CModelException e) { + CPlugin.getDefault().log(e); + e.printStackTrace(); + } + } + + /** + * Processes a delta recursively. When more than two children are affected the + * tree is fully refreshed starting at this node. The delta is processed in the + * current thread but the viewer updates are posted to the UI thread. + */ + protected void processDelta(ICElementDelta delta) throws CModelException { + int kind= delta.getKind(); + int flags= delta.getFlags(); + ICElement element= delta.getElement(); + + //System.out.println("Processing " + element); + // handle open and closing of a solution or project + if (((flags & ICElementDelta.F_CLOSED) != 0) + || ((flags & ICElementDelta.F_OPENED) != 0)) { + postRefresh(element); + } + + if (kind == ICElementDelta.REMOVED) { + Object parent = getParent(element); + postRemove(element); + if (element instanceof ICFile) { + ICFile cfile = (ICFile)element; + if (updateContainer(cfile)) { + postRefresh(parent); + } + } + } + + if (kind == ICElementDelta.ADDED) { + Object parent= getParent(element); + postAdd(parent, element); + if (element instanceof ICFile) { + ICFile cfile = (ICFile)element; + if (updateContainer(cfile)) { + postRefresh(parent); + } + } + } + + if (element instanceof ITranslationUnit) { + if (kind == ICElementDelta.CHANGED) { + postRefresh(element); + return; + } + } + + // we don't show the contents of a compilation or IClassFile, so don't go any deeper + //if (element instanceof ITranslationUnit) + // return; + + //if (isBuildPathChange(delta)) { + // throw the towel and do a full refresh of the affected C project. + //postRefresh(element.getCProject()); + //} + + ICElementDelta[] affectedChildren= delta.getAffectedChildren(); + for (int i= 0; i < affectedChildren.length; i++) { + processDelta(affectedChildren[i]); + } + + // Make sure that containers are updated. + if (element instanceof ICRoot) { + updateContainer((ICRoot)element); + } + } + + private void updateContainer(ICRoot root) { + postRunnable(new Runnable() { + public void run () { + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) { + IStructuredSelection s = (IStructuredSelection)fViewer.getSelection(); + if (s.isEmpty()) + return; + Object element = s.getFirstElement(); + if (element instanceof ICProject) { + updateContainer((ICProject)element); + } + } + } + }); + } + + private boolean updateContainer(ICProject cproject) { + IParent binContainer = cproject.getBinaryContainer(); + IParent libContainer = cproject.getArchiveContainer(); + if (binContainer != null) { + postContainerRefresh(binContainer, cproject); + } + if (libContainer != null) { + postContainerRefresh(libContainer, cproject); + } + return false; + } + + private boolean updateContainer(ICFile cfile) { + IParent container = null; + ICProject cproject = null; + if (cfile.isBinary()) { + IBinary bin = (IBinary)cfile; + if (bin.isExecutable() || bin.isSharedLib()) { + cproject = bin.getCProject(); + container = cproject.getBinaryContainer(); + } + } else if (cfile.isArchive()) { + cproject = cfile.getCProject(); + container = cproject.getArchiveContainer(); + } + if (container != null) { + postContainerRefresh(container, cproject); + return true; + } + return false; + } + + private void postContainerRefresh(final IParent container, final ICProject cproject) { + //System.out.println("UI Container:" + cproject + " " + container); + postRunnable(new Runnable() { + public void run () { + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) { + if (container.hasChildren()) { + if (fViewer.testFindItem(container) != null) { + fViewer.refresh(container); + } else { + fViewer.refresh(cproject); + } + } else { + fViewer.refresh(cproject); + } + } + } + }); + } + + private void postRefresh(final Object root) { + //System.out.println("UI refresh:" + root); + postRunnable(new Runnable() { + public void run() { + // 1GF87WR: ITPUI:ALL - SWTEx + NPE closing a workbench window. + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) + fViewer.refresh(root); + } + }); + } + + private void postAdd(final Object parent, final Object element) { + //System.out.println("UI add:" + parent + " " + element); + postRunnable(new Runnable() { + public void run() { + // 1GF87WR: ITPUI:ALL - SWTEx + NPE closing a workbench window. + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) +// fViewer.add(parent, element); + fViewer.refresh(parent); + } + }); + } + + private void postRemove(final Object element) { + //System.out.println("UI remove:" + element); + postRunnable(new Runnable() { + public void run() { + // 1GF87WR: ITPUI:ALL - SWTEx + NPE closing a workbench window. + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) +// fViewer.remove(element); + fViewer.refresh(getParent(element)); + } + }); + } + + private void postRunnable(final Runnable r) { + Control ctrl= fViewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) + ctrl.getDisplay().asyncExec(r); + } + + /** + * The workbench has changed. Process the delta and issue updates to the viewer, + * inside the UI thread. + * + * @see IResourceChangeListener#resourceChanged + */ + //public void resourceChanged(final IResourceChangeEvent event) { + // final IResourceDelta delta = event.getDelta(); + // Control ctrl = viewer.getControl(); + // if (ctrl != null && !ctrl.isDisposed()) { + // ctrl.getDisplay().syncExec(new Runnable() { + // public void run() { + // processDelta(delta); + // } + // }); + // } + //} + + + /** + * Returns the implementation of IWorkbenchAdapter for the given + * object. Returns null if the adapter is not defined or the + * object is not adaptable. + */ + protected ICElement getAdapter(Object o) { + if (!(o instanceof IAdaptable)) { + return null; + } + return (ICElement)((IAdaptable)o).getAdapter(ICElement.class); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java new file mode 100644 index 00000000000..68e65225bb9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java @@ -0,0 +1,88 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.views.properties.FilePropertySource; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.ResourcePropertySource; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; + +/** + * Implements basic UI support for C elements. + */ +public class CElementAdapterFactory implements IAdapterFactory { + + private static Class[] PROPERTIES= new Class[] { + IPropertySource.class, + IResource.class, + IWorkbenchAdapter.class, + IProject.class, + IWorkspaceRoot.class + }; + + private static CWorkbenchAdapter fgCWorkbenchAdapter= new CWorkbenchAdapter(); + + /** + * @see CElementAdapterFactory#getAdapterList + */ + public Class[] getAdapterList() { + return PROPERTIES; + } + + /** + * @see CElementAdapterFactory#getAdapter + */ + public Object getAdapter(Object element, Class key) { + ICElement celem = (ICElement) element; + IResource res = null; + + try { + if (IPropertySource.class.equals(key)) { + if (celem.getElementType() == ICElement.C_FILE) { + if (celem instanceof IBinary) { + return new BinaryPropertySource((IBinary)celem); + } + IFile file = ((ICFile)celem).getFile(); + if (file != null) { + return new FilePropertySource(file); + } + } else { + try { + res = celem.getCorrespondingResource(); + if (res != null) + return new ResourcePropertySource(res); + } catch (CModelException e) { + } + } + return new CElementPropertySource(celem); + } else if (IWorkspaceRoot.class.equals(key)) { + res = celem.getUnderlyingResource(); + if (res != null) + return res.getWorkspace().getRoot(); + } else if (IProject.class.equals(key)) { + res = celem.getUnderlyingResource(); + if (res != null) + return res.getProject(); + } else if (IResource.class.equals(key)) { + return celem.getUnderlyingResource(); + } else if (IWorkbenchAdapter.class.equals(key)) { + return fgCWorkbenchAdapter; + } + } catch (CModelException e) { + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageDescriptor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageDescriptor.java new file mode 100644 index 00000000000..5d880503206 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageDescriptor.java @@ -0,0 +1,223 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.resource.CompositeImageDescriptor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.Assert; + + +/** + * A JavaImageDescriptor consists of a base image and several adornments. The adornments + * are computed according to the flags either passed during creation or set via the method + * setAdornments. + *

+ * It is guaranteed that objects that conform to this interface are also instances of type + * ImageDescriptor + *

+ * Note: This class/interface is part of an interim API that is still under development + * and expected to change before reaching stability. + *

+ * + * @since 2.0 + */ +public class CElementImageDescriptor extends CompositeImageDescriptor { + + /** Flag to render the abstract adornment */ + public final static int ABSTRACT= 0x001; + + /** Flag to render the final adornment */ + public final static int FINAL= 0x002; + + /** Flag to render the synchronized adornment */ + public final static int SYNCHRONIZED= 0x004; + + /** Flag to render the static adornment */ + public final static int STATIC= 0x008; + + /** Flag to render the runnable adornment */ + public final static int RUNNABLE= 0x010; + + /** Flag to render the waring adornment */ + public final static int WARNING= 0x020; + + /** Flag to render the error adornment */ + public final static int ERROR= 0x040; + + /** Flag to render the 'override' adornment */ + public final static int OVERRIDES= 0x080; + + /** Flag to render the 'implements' adornment */ + public final static int IMPLEMENTS= 0x100; + + private ImageDescriptor fBaseImage; + private int fFlags; + private Point fSize; + + /** + * Create a new JavaElementImageDescriptor. + * + * @param baseImage an image descriptor used as the base image + * @param flags flags indicating which adornments are to be rendered. See setAdornments + * for valid values. + * @param size the size of the resulting image + * @see #setAdornments(int) + */ + public CElementImageDescriptor(ImageDescriptor baseImage, int flags, Point size) { + fBaseImage= baseImage; + Assert.isNotNull(fBaseImage); + fFlags= flags; + Assert.isTrue(fFlags >= 0); + fSize= size; + Assert.isNotNull(fSize); + } + + /** + * Sets the descriptors adornments. Valid values are: ABSTRACT, FINAL, + * SYNCHRONIZED,
STATIC, RUNNABLE, WARNING, + * ERROR, OVERRIDDEN, or any combination of those. + * + * @param adornments the image descritpors adornments + */ + public void setAdornments(int adornments) { + Assert.isTrue(adornments >= 0); + fFlags= adornments; + } + + /** + * Returns the current adornments. + * + * @return the current adornments + */ + public int getAdronments() { + return fFlags; + } + + /** + * Sets the size of the image created by calling createImage(). + * + * @param size the size of the image returned from calling createImage() + */ + public void setImageSize(Point size) { + Assert.isNotNull(size); + Assert.isTrue(size.x >= 0 && size.y >= 0); + fSize= size; + } + + /** + * Returns the size of the image created by calling createImage(). + * + * @return the size of the image created by calling createImage + */ + public Point getImageSize() { + return new Point(fSize.x, fSize.y); + } + + /* (non-Javadoc) + * Method declared in CompositeImageDescriptor + */ + protected Point getSize() { + return fSize; + } + + /* (non-Javadoc) + * Method declared on Object. + */ + public boolean equals(Object object) { + if (!CElementImageDescriptor.class.equals(object.getClass())) + return false; + + CElementImageDescriptor other= (CElementImageDescriptor)object; + return (fBaseImage.equals(other.fBaseImage) && fFlags == other.fFlags && fSize.equals(other.fSize)); + } + + /* (non-Javadoc) + * Method declared on Object. + */ + public int hashCode() { + return fBaseImage.hashCode() | fFlags | fSize.hashCode(); + } + + /* (non-Javadoc) + * Method declared in CompositeImageDescriptor + */ + protected void drawCompositeImage(int width, int height) { + ImageData bg; + if ((bg= fBaseImage.getImageData()) == null) + bg= DEFAULT_IMAGE_DATA; + + drawImage(bg, 0, 0); + drawTopRight(); + drawBottomRight(); + drawBottomLeft(); + } + + private void drawTopRight() { + //int x= getSize().x; + //ImageData data= null; + /* if ((fFlags & ABSTRACT) != 0) { + data= CPluginImages.DESC_OVR_ABSTRACT.getImageData(); + x-= data.width; + drawImage(data, x, 0); + } + if ((fFlags & FINAL) != 0) { + data= CPluginImages.DESC_OVR_FINAL.getImageData(); + x-= data.width; + drawImage(data, x, 0); + } + if ((fFlags & STATIC) != 0) { + data= CPluginImages.DESC_OVR_STATIC.getImageData(); + x-= data.width; + drawImage(data, x, 0); + } */ + } + + private void drawBottomRight() { + //Point size= getSize(); + //int x= size.x; + //ImageData data= null; + /* if ((fFlags & SYNCHRONIZED) != 0) { + data= CPluginImages.DESC_OVR_SYNCH.getImageData(); + x-= data.width; + drawImage(data, x, size.y - data.height); + } + if ((fFlags & RUNNABLE) != 0) { + data= CPluginImages.DESC_OVR_RUN.getImageData(); + x-= data.width; + drawImage(data, x, size.y - data.height); + } + if ((fFlags & OVERRIDES) != 0) { + data= CPluginImages.DESC_OVR_OVERRIDES.getImageData(); + x-= data.width; + drawImage(data, x, size.y - data.height); + } + if ((fFlags & IMPLEMENTS) != 0) { + data= CPluginImages.DESC_OVR_IMPLEMENTS.getImageData(); + x-= data.width; + drawImage(data, x, size.y - data.height); + } */ + } + + private void drawBottomLeft() { + Point size= getSize(); + int x= 0; + ImageData data= null; + if ((fFlags & ERROR) != 0) { + data= CPluginImages.DESC_OVR_ERROR.getImageData(); + drawImage(data, x, size.y - data.height); + x+= data.width; + } + if ((fFlags & WARNING) != 0) { + data= CPluginImages.DESC_OVR_WARNING.getImageData(); + drawImage(data, x, size.y - data.height); + x+= data.width; + } + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageProvider.java new file mode 100644 index 00000000000..2f74d3b352a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementImageProvider.java @@ -0,0 +1,315 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.resource.ImageDescriptor; + +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.internal.ui.util.ImageDescriptorRegistry; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; + +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.model.IWorkbenchAdapter; + + +/** + * Default strategy of the C plugin for the construction of C element icons. + */ +public class CElementImageProvider { + + /** + * Flags for the CImageLabelProvider: + * Generate images with overlays. + */ + public final static int OVERLAY_ICONS= 0x1; + + /** + * Generate small sized images. + */ + public final static int SMALL_ICONS= 0x2; + + /** + * Use the 'light' style for rendering types. + */ + public final static int LIGHT_TYPE_ICONS= 0x4; + + /** + * Show error overrlay. + */ + public final static int OVERLAY_ERROR= 0x8; + + /** + * Show warning overrlay + */ + public final static int OVERLAY_WARNING= 0x10; + + /** + * Show override overrlay. + */ + public final static int OVERLAY_OVERRIDE= 0x20; + + /** + * Show implements overrlay. + */ + public final static int OVERLAY_IMPLEMENTS= 0x40; + + private static final Point SMALL_SIZE= new Point(16, 16); + private static final Point BIG_SIZE= new Point(22, 16); + + private static ImageDescriptor DESC_OBJ_PROJECT_CLOSED; + private static ImageDescriptor DESC_OBJ_PROJECT; + private static ImageDescriptor DESC_OBJ_FOLDER; + { + ISharedImages images= CPlugin.getDefault().getWorkbench().getSharedImages(); + DESC_OBJ_PROJECT_CLOSED= images.getImageDescriptor(ISharedImages.IMG_OBJ_PROJECT_CLOSED); + DESC_OBJ_PROJECT= images.getImageDescriptor(ISharedImages.IMG_OBJ_PROJECT); + DESC_OBJ_FOLDER= images.getImageDescriptor(ISharedImages.IMG_OBJ_FOLDER); + } + + private ImageDescriptorRegistry fRegistry; + + public CElementImageProvider() { + fRegistry= CPlugin.getImageDescriptorRegistry(); + } + + /** + * Returns the icon for a given element. The icon depends on the element type + * and element properties. If configured, overlay icons are constructed for + * ISourceReferences. + * @param flags Flags as defined by the JavaImageLabelProvider + */ + public Image getImageLabel(Object element, int flags) { + ImageDescriptor descriptor= null; + if (element instanceof ICElement) { + descriptor= getCImageDescriptor((ICElement) element, flags); + } + if (descriptor == null && element instanceof ICFile) { + element = ((ICFile)element).getFile(); + } + if (descriptor == null && element instanceof IAdaptable) { + descriptor= getWorkbenchImageDescriptor((IAdaptable) element, flags); + } + if (descriptor != null) { + return fRegistry.get(descriptor); + } + return null; + } + + private boolean showOverlayIcons(int flags) { + return (flags & OVERLAY_ICONS) != 0; + } + + private boolean useLightIcons(int flags) { + return (flags & LIGHT_TYPE_ICONS) != 0; + } + + private boolean useSmallSize(int flags) { + return (flags & SMALL_ICONS) != 0; + } + + /** + * Returns an image descriptor for a C element. The descriptor includes overlays, if specified. + */ + public ImageDescriptor getCImageDescriptor(ICElement element, int flags) { + int adornmentFlags= computeCAdornmentFlags(element, flags); + Point size= useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE; + ImageDescriptor desc = getBaseImageDescriptor(element, flags); + if(desc != null) { + return new CElementImageDescriptor(desc, adornmentFlags, size); + } + return null; + } + + /** + * Returns an image descriptor for a IAdaptable. The descriptor includes overlays, if specified (only error ticks apply). + * Returns null if no image could be found. + */ + public ImageDescriptor getWorkbenchImageDescriptor(IAdaptable adaptable, int flags) { + IWorkbenchAdapter wbAdapter= (IWorkbenchAdapter) adaptable.getAdapter(IWorkbenchAdapter.class); + if (wbAdapter == null) { + return null; + } + ImageDescriptor descriptor= wbAdapter.getImageDescriptor(adaptable); + if (descriptor == null) { + return null; + } + int adornmentFlags= computeBasicAdornmentFlags(adaptable, flags); + Point size= useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE; + return new CElementImageDescriptor(descriptor, adornmentFlags, size); + } + + // ---- Computation of base image key ------------------------------------------------- + + /** + * Returns an image descriptor for a C element. This is the base image, no overlays. + */ + public ImageDescriptor getBaseImageDescriptor(ICElement celement, int renderFlags) { + int type = celement.getElementType(); + switch (type) { + case ICElement.C_CONTAINER: + return CPluginImages.DESC_OBJS_CONTAINER; + + case ICElement.C_FILE: + ICFile cfile = (ICFile)celement; + if (cfile.isArchive()) { + return CPluginImages.DESC_OBJS_ARCHIVE; + } else if (cfile.isBinary()) { + IBinary bin = (IBinary)cfile; + if (bin.isExecutable()) { + if (bin.hasDebug()) + return CPluginImages.DESC_OBJS_CEXEC_DEBUG; + return CPluginImages.DESC_OBJS_CEXEC; + } else if (bin.isSharedLib()) { + return CPluginImages.DESC_OBJS_SHLIB; + } + return CPluginImages.DESC_OBJS_BINARY; + } else if (cfile.isTranslationUnit()) { + return CPluginImages.DESC_OBJS_TUNIT; + } + break; + + case ICElement.C_FOLDER: + return DESC_OBJ_FOLDER; + + case ICElement.C_PROJECT: + ICProject cp= (ICProject)celement; + if (cp.getProject().isOpen()) { + IProject project= cp.getProject(); + IWorkbenchAdapter adapter= (IWorkbenchAdapter)project.getAdapter(IWorkbenchAdapter.class); + if (adapter != null) { + ImageDescriptor result= adapter.getImageDescriptor(project); + if (result != null) + return result; + } + return DESC_OBJ_PROJECT; + } + return DESC_OBJ_PROJECT_CLOSED; + + case ICElement.C_STRUCT: + return CPluginImages.DESC_OBJS_STRUCT; + + case ICElement.C_CLASS: + return CPluginImages.DESC_OBJS_CLASS; + + case ICElement.C_UNION: + return CPluginImages.DESC_OBJS_UNION; + + case ICElement.C_FIELD: + case ICElement.C_VARIABLE: + return CPluginImages.DESC_OBJS_FIELD; + + case ICElement.C_FUNCTION: + return CPluginImages.DESC_OBJS_FUNCTION; + + case ICElement.C_FUNCTION_DECLARATION: + return CPluginImages.DESC_OBJS_DECLARARION; + + case ICElement.C_INCLUDE: + return CPluginImages.DESC_OBJS_INCLUDE; + + case ICElement.C_MACRO: + return CPluginImages.DESC_OBJS_MACRO; + } + return null; + } + + public ImageDescriptor getCElementImageDescriptor(int type) { + switch (type) { + case ICElement.C_CONTAINER: + return CPluginImages.DESC_OBJS_CONTAINER; + + case ICElement.C_FILE: + return CPluginImages.DESC_OBJS_TUNIT; + + case ICElement.C_STRUCT: + return CPluginImages.DESC_OBJS_STRUCT; + + case ICElement.C_CLASS: + return CPluginImages.DESC_OBJS_CLASS; + + case ICElement.C_UNION: + return CPluginImages.DESC_OBJS_UNION; + + case ICElement.C_FIELD: + case ICElement.C_VARIABLE: + return CPluginImages.DESC_OBJS_FIELD; + + case ICElement.C_FUNCTION: + case ICElement.C_FUNCTION_DECLARATION: + return CPluginImages.DESC_OBJS_FUNCTION; + + case ICElement.C_INCLUDE: + return CPluginImages.DESC_OBJS_INCLUDE; + + case ICElement.C_MACRO: + return CPluginImages.DESC_OBJS_MACRO; + } + System.out.println("Unknown base object ype " + type); + return CPluginImages.DESC_OBJS_MACRO; + //return null; + } + + + // ---- Methods to compute the adornments flags --------------------------------- + + private int computeCAdornmentFlags(ICElement element, int renderFlags) { + + int flags= computeBasicAdornmentFlags(element, renderFlags); + + /* if (showOverlayIcons(renderFlags) && element instanceof ISourceReference) { + ISourceReference sourceReference= (ISourceReference)element; + int modifiers= getModifiers(sourceReference); + + if (Flags.isAbstract(modifiers) && confirmAbstract((IMember) sourceReference)) + flags |= JavaElementImageDescriptor.ABSTRACT; + if (Flags.isFinal(modifiers)) + flags |= JavaElementImageDescriptor.FINAL; + if (Flags.isSynchronized(modifiers) && confirmSynchronized((IMember) sourceReference)) + flags |= JavaElementImageDescriptor.SYNCHRONIZED; + if (Flags.isStatic(modifiers)) + flags |= JavaElementImageDescriptor.STATIC; + + if (sourceReference instanceof IType) { + try { + if (JavaModelUtil.hasMainMethod((IType)sourceReference)) + flags |= JavaElementImageDescriptor.RUNNABLE; + } catch (JavaModelException e) { + // do nothing. Can't compute runnable adornment. + } + } + } */ + return flags; + } + + private int computeBasicAdornmentFlags(Object element, int renderFlags) { + int flags= 0; + if ((renderFlags & OVERLAY_ERROR) !=0) { + flags |= CElementImageDescriptor.ERROR; + } + if ((renderFlags & OVERLAY_WARNING) !=0) { + flags |= CElementImageDescriptor.WARNING; + } + if ((renderFlags & OVERLAY_OVERRIDE) !=0) { + flags |= CElementImageDescriptor.OVERRIDES; + } + if ((renderFlags & OVERLAY_IMPLEMENTS) !=0) { + flags |= CElementImageDescriptor.IMPLEMENTS; + } + return flags; + } + + public void dispose() { + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementLabelProvider.java new file mode 100644 index 00000000000..45247eaa0c6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementLabelProvider.java @@ -0,0 +1,220 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Image; + +import org.eclipse.jface.resource.ImageRegistry; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.IBinary; + +/** + * The label provider for the c model elements. + */ +public class CElementLabelProvider extends LabelProvider { + + private ImageRegistry fImageRegistry; + private WorkbenchLabelProvider fWorkbenchLabelProvider; + + private CElementImageProvider fImageLabelProvider; + + private IAdornmentProvider[] fAdornmentProviders; + + private int fImageFlags; + private int fTextFlags; + + public CElementLabelProvider() { + this(0 /* CElementLabels.M_PARAMETER_TYPES */, CElementImageProvider.OVERLAY_ICONS, null); + } + + /** + * @param textFlags Flags defined in JavaElementLabels. + * @param imageFlags Flags defined in JavaElementImageProvider. + */ + public CElementLabelProvider(int textFlags, int imageFlags, IAdornmentProvider[] adormentProviders) { + fImageRegistry= CPlugin.getDefault().getImageRegistry(); + fWorkbenchLabelProvider= new WorkbenchLabelProvider(); + + fImageLabelProvider= new CElementImageProvider(); + fAdornmentProviders= adormentProviders; + + fImageFlags= imageFlags; + fTextFlags= textFlags; + } + + /** + * @see ILabelProvider#getText + */ + public String getText(Object element) { + if (element instanceof ICElement) { + ICElement celem= (ICElement)element; + + String name= celem.getElementName(); + if (celem.getElementType() == ICElement.C_FUNCTION) { + name += "()"; + } else if(celem.getElementType() == ICElement.C_FUNCTION_DECLARATION) { + name += "();"; + } + if (celem instanceof IBinary) { + name += " - [" + ((IBinary)celem).getCPU() + "]"; + } + return name; + } + return fWorkbenchLabelProvider.getText(element); + } + + /** + * @see ILabelProvider#getImage + */ + public Image getImage(Object element) { + int imageFlags= getImageFlags(); + if (fAdornmentProviders != null) { + for (int i= 0; i < fAdornmentProviders.length; i++) { + imageFlags |= fAdornmentProviders[i].computeAdornmentFlags(element); + } + } + + if(element instanceof ICElement) { + Image result= fImageLabelProvider.getImageLabel(element, imageFlags); + if (result != null) { + return result; + } + } + if(element instanceof ICFile) { + //element = ((ICFile)element).getFile(); + } + return fWorkbenchLabelProvider.getImage(element); + + } + + /** + * Gets the image key for a c element. + * @param The type of the element + */ + public static String getCElementImage(ICElement celement) { + int type = celement.getElementType(); + switch (type) { + case ICElement.C_CONTAINER: + return CPluginImages.IMG_OBJS_CONTAINER; + + case ICElement.C_FILE: + ICFile cfile = (ICFile)celement; + if (cfile.isArchive()) { + return CPluginImages.IMG_OBJS_ARCHIVE; + } else if (cfile.isBinary()) { + IBinary bin = (IBinary)cfile; + if (bin.isExecutable()) { + if (bin.hasDebug()) + return CPluginImages.IMG_OBJS_CEXEC_DEBUG; + return CPluginImages.IMG_OBJS_CEXEC; + } else if (bin.isSharedLib()) { + return CPluginImages.IMG_OBJS_SHLIB; + } + return CPluginImages.IMG_OBJS_BINARY; + } else if (cfile.isTranslationUnit()) { + return CPluginImages.IMG_OBJS_TUNIT; + } + break; + + case ICElement.C_UNION: + return CPluginImages.IMG_OBJS_UNION; + + case ICElement.C_CLASS: + return CPluginImages.IMG_OBJS_CLASS; + + case ICElement.C_STRUCT: + return CPluginImages.IMG_OBJS_STRUCT; + + case ICElement.C_FIELD: + case ICElement.C_VARIABLE: + return CPluginImages.IMG_OBJS_FIELD; + + case ICElement.C_FUNCTION: + return CPluginImages.IMG_OBJS_FUNCTION; + + case ICElement.C_FUNCTION_DECLARATION: + return CPluginImages.IMG_OBJS_DECLARATION; + + case ICElement.C_INCLUDE: + return CPluginImages.IMG_OBJS_INCLUDE; + + case ICElement.C_MACRO: + return CPluginImages.IMG_OBJS_MACRO; + } + return null; + } + + /** + * @see IBaseLabelProvider#dispose() + */ + public void dispose() { + if (fAdornmentProviders != null) { + for (int i= 0; i < fAdornmentProviders.length; i++) { + fAdornmentProviders[i].dispose(); + } + } + if (fWorkbenchLabelProvider != null) { + fWorkbenchLabelProvider.dispose(); + fWorkbenchLabelProvider= null; + } + fImageRegistry= null; + if(fImageLabelProvider != null) { + fImageLabelProvider.dispose(); + } + } + + /** + * Sets the textFlags. + * @param textFlags The textFlags to set + */ + public void setTextFlags(int textFlags) { + fTextFlags= textFlags; + } + + /** + * Sets the imageFlags + * @param imageFlags The imageFlags to set + */ + public void setImageFlags(int imageFlags) { + fImageFlags= imageFlags; + } + + /** + * Gets the image flags. + * Can be overwriten by super classes. + * @return Returns a int + */ + public int getImageFlags() { + return fImageFlags; + } + + /** + * Gets the text flags. Can be overwriten by super classes. + * @return Returns a int + */ + public int getTextFlags() { + return fTextFlags; + } + + public static IAdornmentProvider[] getAdornmentProviders(boolean errortick, IAdornmentProvider extra) { + if (errortick) { + if (extra == null) { + return new IAdornmentProvider[] { new ErrorTickAdornmentProvider() }; + } else { + return new IAdornmentProvider[] { new ErrorTickAdornmentProvider(), extra }; + } + } + if (extra != null) { + return new IAdornmentProvider[] { extra }; + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementProperties.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementProperties.java new file mode 100644 index 00000000000..556cccac4ef --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementProperties.java @@ -0,0 +1,79 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.PropertyDescriptor; + +import org.eclipse.cdt.core.model.ICElement; + +public class CElementProperties implements IPropertySource { + + private final static String LABEL= "CElementProperties.name"; + + private ICElement fCElement; + + // Property Descriptors + static private IPropertyDescriptor[] fgPropertyDescriptors; + + static { + // resource name + String displayName= CPlugin.getResourceString(LABEL); + PropertyDescriptor descriptor= new PropertyDescriptor(IBasicPropertyConstants.P_TEXT, displayName); + descriptor.setAlwaysIncompatible(true); + + fgPropertyDescriptors= new IPropertyDescriptor[] { descriptor }; + } + + public CElementProperties(ICElement elem) { + fCElement= elem; + } + + /** + * @see IPropertySource#getPropertyDescriptors + */ + public IPropertyDescriptor[] getPropertyDescriptors() { + return fgPropertyDescriptors; + } + + /** + * @see IPropertySource#getPropertyValue + */ + public Object getPropertyValue(Object name) { + if (name.equals(IBasicPropertyConstants.P_TEXT)) { + return fCElement.getElementName(); + } + return null; + } + + /** + * @see IPropertySource#setPropertyValue + */ + public void setPropertyValue(Object name, Object value) { + } + + /** + * @see IPropertySource#getEditableValue + */ + public Object getEditableValue() { + return null; + } + + /** + * @see IPropertySource#isPropertySet + */ + public boolean isPropertySet(Object property) { + return false; + } + + /** + * @see IPropertySource#resetPropertyValue + */ + public void resetPropertyValue(Object property) { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementPropertySource.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementPropertySource.java new file mode 100644 index 00000000000..5b2b88260dc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementPropertySource.java @@ -0,0 +1,79 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.PropertyDescriptor; + +import org.eclipse.cdt.core.model.ICElement; + +public class CElementPropertySource implements IPropertySource { + + private final static String LABEL= "CElementProperties.name"; + + private ICElement fCElement; + + // Property Descriptors + static private IPropertyDescriptor[] fgPropertyDescriptors; + + static { + // resource name + String displayName= CPlugin.getResourceString(LABEL); + PropertyDescriptor descriptor= new PropertyDescriptor(IBasicPropertyConstants.P_TEXT, displayName); + descriptor.setAlwaysIncompatible(true); + + fgPropertyDescriptors= new IPropertyDescriptor[] { descriptor }; + } + + public CElementPropertySource(ICElement elem) { + fCElement= elem; + } + + /** + * @see IPropertySource#getPropertyDescriptors + */ + public IPropertyDescriptor[] getPropertyDescriptors() { + return fgPropertyDescriptors; + } + + /** + * @see IPropertySource#getPropertyValue + */ + public Object getPropertyValue(Object name) { + if (name.equals(IBasicPropertyConstants.P_TEXT)) { + return fCElement.getElementName(); + } + return null; + } + + /** + * @see IPropertySource#setPropertyValue + */ + public void setPropertyValue(Object name, Object value) { + } + + /** + * @see IPropertySource#getEditableValue + */ + public Object getEditableValue() { + return null; + } + + /** + * @see IPropertySource#isPropertySet + */ + public boolean isPropertySet(Object property) { + return false; + } + + /** + * @see IPropertySource#resetPropertyValue + */ + public void resetPropertyValue(Object property) { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java new file mode 100644 index 00000000000..30f0994840e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java @@ -0,0 +1,63 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; + +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.internal.core.model.TranslationUnit; +import org.eclipse.cdt.internal.core.DocumentInputStream; + +public class CFileElementWorkingCopy extends TranslationUnit { + + private IDocumentProvider fProvider; + //private IFileEditorInput input; + private IEditorInput input; + + /** + * Creates a working copy of this element + */ + public CFileElementWorkingCopy(IFileEditorInput fileInput, IDocumentProvider provider) throws CoreException { + super(null, fileInput.getFile()); + input= fileInput; + fProvider= provider; + } + + /** + * Creates a working copy of this element + */ + public CFileElementWorkingCopy(IStorageEditorInput StoreInput, IDocumentProvider provider) throws CoreException { + super(null, new Path(StoreInput.getName())); + input = StoreInput; + fProvider = provider; + IStorage storage = StoreInput.getStorage(); + super.setLocation(storage.getFullPath()); + } + + /** + * @see CFileElement#update + */ + public void update() throws CoreException { + IDocument doc= fProvider.getDocument(input); + if (doc != null) { + DocumentInputStream dis= new DocumentInputStream(doc); + try { + parse(dis); + } finally { + try { dis.close(); } catch (IOException e) {} + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPerspectiveFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPerspectiveFactory.java new file mode 100644 index 00000000000..54f48ec48fb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPerspectiveFactory.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.search.ui.SearchUI; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +public class CPerspectiveFactory implements IPerspectiveFactory { + + /** + * Constructs a new Default layout engine. + */ + public CPerspectiveFactory() { + super(); + } + + /** + * @see IPerspectiveFactory#createInitialLayout + */ + public void createInitialLayout(IPageLayout layout) { + String editorArea = layout.getEditorArea(); + + IFolderLayout folder1= layout.createFolder("topLeft", IPageLayout.LEFT, (float)0.25, editorArea); + folder1.addView(CPlugin.CVIEW_ID); + folder1.addView(IPageLayout.ID_RES_NAV); + folder1.addPlaceholder(IPageLayout.ID_BOOKMARKS); + + IFolderLayout folder2= layout.createFolder("bottom", IPageLayout.BOTTOM, (float)0.75, editorArea); + folder2.addView(IPageLayout.ID_TASK_LIST); + folder2.addView(CPlugin.CONSOLE_ID); + folder2.addView(IPageLayout.ID_PROP_SHEET); + + IFolderLayout folder3= layout.createFolder("topRight", IPageLayout.RIGHT,(float)0.75, editorArea); + folder3.addView(IPageLayout.ID_OUTLINE); + folder3.addView(CPlugin.MAKEVIEW_ID); + +// layout.addActionSet(CPlugin.WIZARD_ACTION_SET_ID); + layout.addActionSet(CPlugin.FOLDER_ACTION_SET_ID); + + // views - build console + layout.addShowViewShortcut(CPlugin.CONSOLE_ID); + + // views - searching + layout.addShowViewShortcut(SearchUI.SEARCH_RESULT_VIEW_ID); + + // views - standard workbench + layout.addShowViewShortcut(IPageLayout.ID_OUTLINE); + layout.addShowViewShortcut(IPageLayout.ID_TASK_LIST); + layout.addShowViewShortcut(CPlugin.CVIEW_ID); + layout.addShowViewShortcut(IPageLayout.ID_RES_NAV); + layout.addShowViewShortcut(IPageLayout.ID_PROP_SHEET); + + // new actions - C project creation wizard + layout.addNewWizardShortcut(CPlugin.FILE_WIZARD_ID); + layout.addNewWizardShortcut(CPlugin.FOLDER_WIZARD_ID); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPlugin.java new file mode 100644 index 00000000000..29872413b21 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPlugin.java @@ -0,0 +1,382 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdapterManager; +import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.resources.ICPlugin; +import org.eclipse.cdt.core.resources.IConsole; +import org.eclipse.cdt.core.resources.IMessageDialog; +import org.eclipse.cdt.core.resources.IPropertyStore; +import org.eclipse.cdt.internal.CCorePlugin; +import org.eclipse.cdt.internal.ui.cview.CView; +import org.eclipse.cdt.internal.ui.editor.CDocumentProvider; +import org.eclipse.cdt.internal.ui.editor.asm.AsmTextTools; +import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage; +import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.util.ImageDescriptorRegistry; +import org.eclipse.cdt.internal.ui.util.ProblemMarkerManager; + + +public class CPlugin extends AbstractUIPlugin implements ICPlugin { + + public static final String PLUGIN_ID= "org.eclipse.cdt.ui"; + public static final String PLUGIN_CORE_ID= "org.eclipse.cdt.core"; + public static final String EDITOR_ID= PLUGIN_ID + ".editor.CEditor"; + public static final String CONSOLE_ID= PLUGIN_ID + ".BuildConsoleView"; + public static final String CVIEW_ID= PLUGIN_ID + ".CView"; + public static final String MAKEVIEW_ID= PLUGIN_ID + ".MakeView"; + public static final String C_PROBLEMMARKER= PLUGIN_CORE_ID + ".problem"; + + public static final String C_PROJECT_WIZARD_ID= PLUGIN_ID + ".wizards.StdCWizard"; + public static final String CPP_PROJECT_WIZARD_ID= PLUGIN_ID + ".wizards.StdCCWizard"; + + public static final String FILE_WIZARD_ID= PLUGIN_ID + ".wizards.new.BasicNewFileResourceWizard"; + public static final String FOLDER_WIZARD_ID= PLUGIN_ID + ".wizards.new.BasicNewFolderResourceWizard"; + + public static final String FOLDER_ACTION_SET_ID= PLUGIN_ID + ".CFolderActionSet"; + public static final String BUILDER_ID= PLUGIN_CORE_ID + ".cbuilder"; + + private static CPlugin fgCPlugin; + private static ResourceBundle fgResourceBundle; + private ImageDescriptorRegistry fImageDescriptorRegistry; + + static String SEPARATOR = System.getProperty("file.separator"); + + // -------- static methods -------- + + static { + try { + fgResourceBundle= ResourceBundle.getBundle("org.eclipse.cdt.internal.ui.CPluginResources"); + } catch (MissingResourceException x) { + fgResourceBundle= null; + } + } + + public static String getResourceString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!"; + } catch (NullPointerException e) { + return "#" + key + "#"; + } + } + + public static IWorkspace getWorkspace() { + return ResourcesPlugin.getWorkspace(); + } + + public static String getFormattedString(String key, String arg) { + return MessageFormat.format(getResourceString(key), new String[] { arg }); + } + + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getResourceString(key), args); + } + + public static ResourceBundle getResourceBundle() { + return fgResourceBundle; + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return getDefault().getWorkbench().getActiveWorkbenchWindow(); + } + + public static Shell getActiveWorkbenchShell() { + return getActiveWorkbenchWindow().getShell(); + } + + public static CPlugin getDefault() { + return fgCPlugin; + } + + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, "Error", e)); + } + + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + // ------ CPlugin + + public IMessageDialog getMessageDialog() { + return new IMessageDialog() { + public void openError(String title, String msg) { + MessageDialog.openError(getActiveWorkbenchShell(), title, msg); + } + }; + } + + private ConsoleDocument fConsoleDocument; + private CoreModel fCoreModel; + private CDocumentProvider fDocumentProvider; + private CTextTools fTextTools; + private AsmTextTools fAsmTextTools; + private ProblemMarkerManager fProblemMarkerManager; + + static class ConsoleDocument extends ConsoleOutputStream implements IConsole { + private IDocument fDocument; + + public ConsoleDocument() { + fDocument = new Document(); + } + + public void clear() { + super.clear(); + Display.getDefault().syncExec(new Runnable() { + public void run() { + fDocument.set(""); + fContent.setLength(0); + } + }); + } + + public ConsoleOutputStream getOutputStream() { + return this; + } + + public IDocument getDocument() { + return fDocument; + } + + public synchronized void flush() throws IOException { + super.flush(); + Display.getDefault().asyncExec(new Runnable() { + public void run() { + if (CPluginPreferencePage.isConsoleOnTop()) + bringConsoleOnTop(); + try { + int len = fDocument.getLength (); + fDocument.replace(len, 0, getContent(len)); + } catch (BadLocationException x) { + } + } + }); + } + + void bringConsoleOnTop () { + IWorkbenchWindow window = getActiveWorkbenchWindow(); + if ( window == null ) + return; + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + try { + // show the build console + IViewPart cBuild = page.findView(CPlugin.CONSOLE_ID); + if(cBuild == null) { + if(CPluginPreferencePage.isAutoOpenConsole()) { + IWorkbenchPart activePart = page.getActivePart(); + cBuild = page.showView(CPlugin.CONSOLE_ID); + //restore focus + page.activate(activePart); + } + } else { + page.bringToTop(cBuild); + } + } catch (PartInitException pie) { + } + } + } + } + + private IPropertyStore fPropertyStore; + + public IPropertyStore getPropertyStore() { + if (fPropertyStore == null) { + fPropertyStore = new IPropertyStore() { + public String getString(String name) { + return getPreferenceStore().getString(name); + } + public void putValue(String name, String value) { + getPreferenceStore().putValue(name, value); + } + public void setDefault(String name, String def) { + getPreferenceStore().setDefault(name, def); + } + }; + } + return fPropertyStore; + } + + // protected ACDebugModel fModel; + + public CPlugin(IPluginDescriptor descriptor) { + super(descriptor); + fgCPlugin= this; +/* + fModel = new ACDebugModel() { + public Object createPresentation() { + return new CDebugModelPresentation(); + } + + public String getIdentifier() { + return PLUGIN_ID; + } + + public IMarker createBreakpoint( final IResource resource, + final Map attributes, + final String markerType ) throws CoreException { + + class BreakpointRunnable implements IWorkspaceRunnable { + IMarker fBreakpoint = null; + + public void run( IProgressMonitor monitor ) throws CoreException + { + fBreakpoint = resource.createMarker( markerType ); + fBreakpoint.setAttributes( attributes ); + } + }; + BreakpointRunnable r = new BreakpointRunnable(); + + resource.getWorkspace().run( r, null ); + + return r.fBreakpoint; + } + }; +*/ + fConsoleDocument= new ConsoleDocument(); + fDocumentProvider= null; + fTextTools= null; + } + + /** + * Returns the used document provider + */ + public CDocumentProvider getDocumentProvider() { + if (fDocumentProvider == null) { + fDocumentProvider= new CDocumentProvider(); + } + return fDocumentProvider; + } + + /** + * Returns the shared text tools + */ + public CTextTools getTextTools() { + if (fTextTools == null) + fTextTools= new CTextTools(); + return fTextTools; + } + + /** + * Returns the shared assembly text tools + */ + public AsmTextTools getAsmTextTools() { + if (fAsmTextTools == null) + fAsmTextTools= new AsmTextTools(); + return fAsmTextTools; + } + /** + * @see Plugin#shutdown + */ + public void shutdown() throws CoreException { + if (fTextTools != null) { + fTextTools.dispose(); + } + if (fImageDescriptorRegistry != null) + fImageDescriptorRegistry.dispose(); + super.shutdown(); + } + + /** + * @see Plugin#startup + */ + public void startup() throws CoreException { + super.startup(); + IAdapterManager manager= Platform.getAdapterManager(); + manager.registerAdapters(new ResourceAdapterFactory(), IResource.class); + manager.registerAdapters(new CElementAdapterFactory(), ICElement.class); + manager.registerAdapters(new PluginAdapterFactory(), CCorePlugin.class); + CPluginImages.initialize(); + + } + + /** + * @see AbstractUIPlugin#initializeDefaultPreferences + */ + protected void initializeDefaultPreferences(IPreferenceStore store) { + super.initializeDefaultPreferences(store); + CPluginPreferencePage.initDefaults(store); + CEditorPreferencePage.initDefaults(store); + CView.initDefaults(store); + } + + public IConsole getConsole() { + return fConsoleDocument; + } + + public IDocument getConsoleDocument() { + return fConsoleDocument.getDocument(); + } + + public CoreModel getCoreModel() { + return fCoreModel; + } + + public Object getAdapter(Class adapter) { + return Platform.getAdapterManager().getAdapter(this, adapter); + } + +/* + public ACDebugModel getDebugModel() { + return fModel; + } +*/ + public static String getPluginId() { + return PLUGIN_ID; + } + + public static ImageDescriptorRegistry getImageDescriptorRegistry() { + return getDefault().internalGetImageDescriptorRegistry(); + } + + private ImageDescriptorRegistry internalGetImageDescriptorRegistry() { + if (fImageDescriptorRegistry == null) + fImageDescriptorRegistry= new ImageDescriptorRegistry(); + return fImageDescriptorRegistry; + } + + /** + * Returns the problem marker manager + */ + public ProblemMarkerManager getProblemMarkerManager() { + if (fProblemMarkerManager == null) + fProblemMarkerManager= new ProblemMarkerManager(); + return fProblemMarkerManager; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java new file mode 100644 index 00000000000..e9079a20188 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -0,0 +1,175 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.net.MalformedURLException; +import java.net.URL; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; + +/** + * Bundle of all images used by the C plugin. + */ +public class CPluginImages { + + // The plugin registry + private static ImageRegistry imageRegistry = new ImageRegistry(); + + // Subdirectory (under the package containing this class) where 16 color images are + private static URL fgIconBaseURL; + static { + try { + fgIconBaseURL= new URL(CPlugin.getDefault().getDescriptor().getInstallURL(), "icons/" ); + } catch (MalformedURLException e) { + CPlugin.log(e); + } + } + private static final String NAME_PREFIX= CPlugin.PLUGIN_ID + '.'; + private static final int NAME_PREFIX_LENGTH= NAME_PREFIX.length(); + private static final String T= "full/"; + + public static final String T_OBJ= T + "obj16/"; + public static final String T_WIZBAN= T + "wizban/"; + public static final String T_LCL= "lcl16/"; + public static final String T_TOOL= "tool16/"; + public static final String T_VIEW= "view16/"; + public static final String T_OVR= T + "ovr16/"; + + public static final String IMG_OBJS_TEMPLATE= NAME_PREFIX + "template_obj.gif"; + public static final String IMG_OBJS_FIELD= NAME_PREFIX + "field_obj.gif"; + public static final String IMG_OBJS_CLASS= NAME_PREFIX + "class_obj.gif"; + public static final String IMG_OBJS_STRUCT= NAME_PREFIX + "struct_obj.gif"; + public static final String IMG_OBJS_UNION= NAME_PREFIX + "union_obj.gif"; + public static final String IMG_OBJS_FUNCTION= NAME_PREFIX + "function_obj.gif"; + public static final String IMG_OBJS_DECLARATION= NAME_PREFIX + "cdeclaration_obj.gif"; + public static final String IMG_OBJS_INCLUDE= NAME_PREFIX + "include_obj.gif"; + public static final String IMG_OBJS_MACRO= NAME_PREFIX + "define_obj.gif"; + public static final String IMG_OBJS_TUNIT= NAME_PREFIX + "c_file_obj.gif"; + public static final String IMG_OBJS_ARCHIVE= NAME_PREFIX + "ar_obj.gif"; + public static final String IMG_OBJS_BINARY= NAME_PREFIX + "bin_obj.gif"; + public static final String IMG_OBJS_SHLIB= NAME_PREFIX + "shlib_obj.gif"; + public static final String IMG_OBJS_CEXEC= NAME_PREFIX + "exec_obj.gif"; + public static final String IMG_OBJS_CEXEC_DEBUG= NAME_PREFIX + "exec_dbg_obj.gif"; + public static final String IMG_OBJS_CONTAINER= NAME_PREFIX + "container_obj.gif"; + + // Breakpoint images + public static final String IMG_OBJS_BREAKPOINT = NAME_PREFIX + "breakpoint.gif"; + public static final String IMG_OBJS_BREAKPOINT_DISABLED = NAME_PREFIX + "breakpoint_disabled.gif"; + public static final String IMG_OBJS_BREAKPOINT_ACTIVE = NAME_PREFIX + "breakpoint_active.gif"; + + public static final ImageDescriptor DESC_OBJS_FIELD= createManaged(T_OBJ, IMG_OBJS_FIELD); + public static final ImageDescriptor DESC_OBJS_CLASS= createManaged(T_OBJ, IMG_OBJS_CLASS); + public static final ImageDescriptor DESC_OBJS_STRUCT= createManaged(T_OBJ, IMG_OBJS_STRUCT); + public static final ImageDescriptor DESC_OBJS_UNION= createManaged(T_OBJ, IMG_OBJS_UNION); + public static final ImageDescriptor DESC_OBJS_FUNCTION= createManaged(T_OBJ, IMG_OBJS_FUNCTION); + public static final ImageDescriptor DESC_OBJS_DECLARARION= createManaged(T_OBJ, IMG_OBJS_DECLARATION); + public static final ImageDescriptor DESC_OBJS_INCLUDE= createManaged(T_OBJ, IMG_OBJS_INCLUDE); + public static final ImageDescriptor DESC_OBJS_MACRO= createManaged(T_OBJ, IMG_OBJS_MACRO); + public static final ImageDescriptor DESC_OBJS_TUNIT= createManaged(T_OBJ, IMG_OBJS_TUNIT); + public static final ImageDescriptor DESC_OBJS_ARCHIVE= createManaged(T_OBJ, IMG_OBJS_ARCHIVE); + public static final ImageDescriptor DESC_OBJS_BINARY= createManaged(T_OBJ, IMG_OBJS_BINARY); + public static final ImageDescriptor DESC_OBJS_SHLIB= createManaged(T_OBJ, IMG_OBJS_SHLIB); + public static final ImageDescriptor DESC_OBJS_CEXEC= createManaged(T_OBJ, IMG_OBJS_CEXEC); + public static final ImageDescriptor DESC_OBJS_CEXEC_DEBUG= createManaged(T_OBJ, IMG_OBJS_CEXEC_DEBUG); + public static final ImageDescriptor DESC_OBJS_CONTAINER= createManaged(T_OBJ, IMG_OBJS_CONTAINER); + + // Breakpoint image descriptors + public static final ImageDescriptor DESC_OBJS_BREAKPOINT = createManaged( T_OBJ, IMG_OBJS_BREAKPOINT ); + public static final ImageDescriptor DESC_OBJS_BREAKPOINT_DISABLED = createManaged( T_OBJ, IMG_OBJS_BREAKPOINT_DISABLED ); + public static final ImageDescriptor DESC_OBJS_BREAKPOINT_ACTIVE = createManaged( T_OBJ, IMG_OBJS_BREAKPOINT_ACTIVE ); + + public static final String IMG_MENU_SHIFT_RIGHT= NAME_PREFIX + "shift_r_edit.gif"; + public static final String IMG_MENU_SHIFT_LEFT= NAME_PREFIX + "shift_l_edit.gif"; + public static final String IMG_MENU_OPEN_INCLUDE= NAME_PREFIX + "open_incl.gif"; + public static final String IMG_CLEAR_CONSOLE= NAME_PREFIX + "clear_co.gif"; + public static final String IMG_ALPHA_SORTING= NAME_PREFIX + "alphab_sort_co.gif"; + public static final String IMG_TOOL_GOTO_PREV_ERROR= NAME_PREFIX + "prev_error_nav.gif"; + public static final String IMG_TOOL_GOTO_NEXT_ERROR= NAME_PREFIX + "next_error_nav.gif"; + public static final String IMG_EDIT_PROPERTIES= NAME_PREFIX + "prop_edt.gif"; + public static final ImageDescriptor DESC_OBJS_TEMPLATE= createManaged(T_OBJ, IMG_OBJS_TEMPLATE); + + public static final ImageDescriptor DESC_OVR_STATIC= create(T_OVR, "static_co.gif");//$NON-NLS-1$ + + public static final ImageDescriptor DESC_OVR_WARNING= create(T_OVR, "warning_co.gif"); + public static final ImageDescriptor DESC_OVR_ERROR= create(T_OVR, "error_co.gif"); + + public static final ImageDescriptor DESC_WIZABAN_NEW_PROJ= create(T_WIZBAN, "newcprj_wiz.gif"); + public static final ImageDescriptor DESC_WIZABAN_C_APP= create(T_WIZBAN, "c_app_wiz.gif"); + public static final String IMG_OBJS_PROJECT = NAME_PREFIX + "prj_obj.gif"; + public static final ImageDescriptor DESC_PROJECT= createManaged(T_WIZBAN, IMG_OBJS_PROJECT); + + // For the build image + public static final String IMG_OBJS_BUILD= NAME_PREFIX + "build_menu.gif"; + public static final ImageDescriptor DESC_BUILD_MENU = createManaged(T_OBJ, IMG_OBJS_BUILD); + + public static void initialize() { + //createManaged(registry, T_OBJ, IMG_OBJS_TUNIT); + //createManaged(registry, T_OBJ, IMG_OBJS_FIELD); + //createManaged(registry, T_OBJ, IMG_OBJS_CLASS); + //createManaged(registry, T_OBJ, IMG_OBJS_STRUCT); + //createManaged(registry, T_OBJ, IMG_OBJS_UNION); + //createManaged(registry, T_OBJ, IMG_OBJS_FUNCTION); + //createManaged(registry, T_OBJ, IMG_OBJS_INCLUDE); + //createManaged(registry, T_OBJ, IMG_OBJS_DEFINE); + + //createManaged(registry, T_OBJ, IMG_OBJS_ARCHIVE); + //createManaged(registry, T_OBJ, IMG_OBJS_SHLIB); + //createManaged(registry, T_OBJ, IMG_OBJS_BINARY); + //createManaged(registry, T_OBJ, IMG_OBJS_CEXEC); + //createManaged(registry, T_OBJ, IMG_OBJS_CEXEC_DEBUG); + //createManaged(registry, T_OBJ, IMG_OBJS_CONTAINER); + + //createManaged(registry, T_OBJ, IMG_OBJS_TEMPLATE); + } + + private static ImageDescriptor createManaged(String prefix, String name) { + return createManaged(imageRegistry, prefix, name); + } + + private static ImageDescriptor createManaged(ImageRegistry registry, String prefix, String name) { + ImageDescriptor result= ImageDescriptor.createFromURL(makeIconFileURL(prefix, name.substring(NAME_PREFIX_LENGTH))); + registry.put(name, result); + return result; + } + + public static Image get(String key) { + return imageRegistry.get(key); + } + + private static ImageDescriptor create(String prefix, String name) { + return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name)); + } + + private static URL makeIconFileURL(String prefix, String name) { + StringBuffer buffer= new StringBuffer(prefix); + buffer.append(name); + try { + return new URL(fgIconBaseURL, buffer.toString()); + } catch (MalformedURLException e) { + CPlugin.log(e); + return null; + } + } + + /** + * Sets all available image descriptors for the given action. + */ + public static void setImageDescriptors(IAction action, String type, String relPath) { + relPath= relPath.substring(NAME_PREFIX_LENGTH); + action.setDisabledImageDescriptor(create(T + "d" + type, relPath)); + action.setHoverImageDescriptor(create(T + "c" + type, relPath)); + action.setImageDescriptor(create(T + "e" + type, relPath)); + } + + /** + * Helper method to access the image registry from the JavaPlugin class. + */ + static ImageRegistry getImageRegistry() { + return imageRegistry; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties new file mode 100644 index 00000000000..5db1ea9c1cb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties @@ -0,0 +1,243 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +# ------- CView ----------------- +CView.make_edit_action =Project properties + +# ------- Preference Page ------- + +#CBasePreferencePage.description=The build command is an executable program which will be used by the builder\nto build your C project. If the build command is not on the current system\nenvironment path, you have to enter an absolute path name.\nThe command given here will be filled in new C projects by default.\nTo change the builder for a specific project, use the project's property page. +CBasePreferencePage.description=The build command is an executable program which will be used by the builder\nto build your C/C++ project. If the build command is not on the current system\nenvironment path, you have to enter an absolute path name.\nThe command given here will be filled in new C/C++ projects by default. +CBasePreferencePage.buildLocation.label=Default build command: +CBasePreferencePage.clearConsole.label=Always clear C-Build view before building +CBasePreferencePage.autoOpenConsole.label=Open C-Build view when building +CBasePreferencePage.consoleOnTop.label=Bring C-Build view to top when building (if present) +CBasePreferencePage.linkToEditor.label=Link view selection to active editor +CBasePreferencePage.CUChildren.label=Show file members in Project View + +CBasePreferencePage.editorFont.label=C Editor font: +CBasePreferencePage.consoleFont.label=C-Build view font: + +CBasePreferencePage.bracketHighlightBox.label=Highlight matching brackets with box +CBasePreferencePage.bracketHighlightClr.label=Highlight matching brackets with color +CBasePreferencePage.bracketColour.label=Bracket highlighting color + +OpenProjectWizardAction.title=New Project +OpenNewFileWizardAction.title=New File +OpenNewFolderWizardAction.title=New Folder + +# ------- NewProjectCreationPluginPage------- + +CProjectWizardPage.nameLabel=Name: +CProjectWizardPage.useDefaultLabel=Use Default Location +CProjectWizardPage.locationLabel=Location: +CProjectWizardPage.browseLabel=Browse... +CProjectWizardPage.projectNameEmpty=Project name must be specified. +CProjectWizardPage.projectContainsSpace=Project name contains space. +CProjectWizardPage.defaultLocationError=Location path can not overlap with default location. +CProjectWizardPage.projectExistsMessage=Project already exists. + +# ------- ProjectConfigurationBlock------- + +ProjectConfigurationBlock.buildCmdText.label=The build command is an executable program which will be used by the builder to build your C project. If the build command is not on the current system environment path, you have to enter an absolute path name. If the build command is make then it will use the makefile which is located in the project folder +ProjectConfigurationBlock.buildArgsText.label=Build can be either incremental or full. You can specify different build arguments\nfor the two kinds. +ProjectConfigurationBlock.buildArgText.label=Additional build arguments + +ProjectConfigurationBlock.buildLocation.label=Build command: +ProjectConfigurationBlock.buildLocation.button=Browse... +ProjectConfigurationBlock.fullBuildArguments.label=Full Build Arguments: +ProjectConfigurationBlock.incrBuildArguments.label=Incremental Build Arguments: +ProjectConfigurationBlock.error.InvalidBuildCommand=Invalid build command + +# --- The new wizards ---- +# FIXME: Remove the properties above when satisfy with wizards. +ReferenceBlock.label= Projects +ReferenceBlock.desc= Referenced Projects + +SettingsBlock.label=Build Settings +SettingsBlock.keepOnGoing=Keep Going On Error +SettingsBlock.stopOnError=Stop On Error +SettingsBlock.makeOption.label=Build Command +SettingsBlock.makeOption.use_default=Use Default +SettingsBlock.makeOption.build_cmd=Build Command: + +StdMakeProjectWizard.op_error=Standard Make Error +StdMakeProjectWizard.title=Standard Make Project +StdMakeProjectWizard.description=Create a new Standard Make project. +StdMakeProjectWizardSettings.title=Standard Make Settings +StdMakeProjectWizardSettings.description=Define the Standard Make build settings. + +StdCWizard.title=Standard Make C Project +StdCWizard.description=Create a new Standard Make C project. +StdCWizardSettings.title=Standard Make C Settings +StdCWizardSettings.description=Define the Standard Make C build settings. + +StdCCWizard.title=Standard Make C++ Project +StdCCWizard.description=Create a new Standard Make C++ Project. +StdCCWizardSettings.title=Standard Make C++ Settings +StdCCWizardSettings.description=Define the Standard Make C++ build settings + +CProjectWizard.op_description=C Project Wizard +CProjectWizard.windowTitle=New Project +CProjectWizard.description=C Project Wizard +CProjectWizard.title=C Project Wizard +CProjectWizardPage=C Wizard Page +TabFolderPage=Tab Folder Page +TabFolderPage.title=Project +TabFolderPage.desc=Project Settings + +# ------- CProjectPropertyPage------- + +CProjectPropertyPage.nocproject=Not a C builder +CProjectPropertyPage.closedproject=C information is not available for a closed project + +# ------- Building ------- + +CBuilder.build_error=Could not execute builder "{0}" configured in the project property page. + +# ------- Properties------- + +CElementProperties.name=name +CElementProperties.elf_cpu=cpu +CElementProperties.elf_text=text +CElementProperties.elf_data=data +CElementProperties.elf_bss=bss +CElementProperties.elf_type=type +CElementProperties.elf_soname=soname +CElementProperties.elf_has_debug=debug +CElementProperties.elf_needed=needed + +# ------- Compare ------- + +CMergeViewer.title=C Compare Viewer +CStructureCreator.name=C Compare + +# ------- Editor ------------ + +Editor.Undo.label=Undo@Ctrl+Z +Editor.Undo.tooltip=Undo +Editor.Undo.image= +Editor.Undo.description=Undo + +Editor.Redo.label=Redo@Ctrl+Y +Editor.Redo.tooltip=Redo +Editor.Redo.image= +Editor.Redo.description=Redo + +Editor.Cut.label=Cut@Ctrl+X +Editor.Cut.tooltip=Cut +Editor.Cut.image= +Editor.Cut.description=Cut + +Editor.Copy.label=&Copy@Ctrl+C +Editor.Copy.tooltip=Copy +Editor.Copy.image= +Editor.Copy.description=Copy + +Editor.Paste.label=Paste@Ctrl+V +Editor.Paste.tooltip=Paste +Editor.Paste.image= +Editor.Paste.description=Paste + +Editor.Delete.label=Delete@Delete +Editor.Delete.tooltip=Delete +Editor.Delete.image= +Editor.Delete.description=Delete + +Editor.SelectAll.label=Select &All@Ctrl+A +Editor.SelectAll.tooltip=Select All +Editor.SelectAll.image= +Editor.SelectAll.description=Select All + +Editor.ShiftRight.label=Sh&ift Right@Ctrl+I +Editor.ShiftRight.tooltip=Shift Right +Editor.ShiftRight.image= +Editor.ShiftRight.description=Shift the selected text to the right + +Editor.ShiftLeft.label=S&hift Left@Ctrl+Shift+I +Editor.ShiftLeft.tooltip=Shift Left +Editor.ShiftLeft.image= +Editor.ShiftLeft.description=Shift the selected text to the left + +Editor.FindReplace.label=Find/Replace...@Ctrl+F +Editor.FindReplace.tooltip=Find/Replace +Editor.FindReplace.image= +Editor.FindReplace.description=Find/Replace + +Editor.AddBookmark.label=Boo&kmark... +Editor.AddBookmark.tooltip=Bookmark +Editor.AddBookmark.image= +Editor.AddBookmark.description=Add Bookmark +Editor.AddBookmark.dialog.title=Add Bookmark +Editor.AddBookmark.dialog.message=Enter Bookmark name + +Editor.AddTask.label=&Task... +Editor.AddTask.tooltip=Task +Editor.AddTask.image= +Editor.AddTask.description=Add Task + +Editor.Save.label=Save@Ctrl+S +Editor.Save.tooltip=Save +Editor.Save.image= +Editor.Save.description=Save + +Editor.Revert.label=Re&vert +Editor.Revert.tooltip=Revert +Editor.Revert.image= +Editor.Revert.description=Revert + +Editor.GotoLine.label=&Go to Line...@Ctrl+L +Editor.GotoLine.tooltip=Go to a Line +Editor.GotoLine.image= +Editor.GotoLine.description=Go to a line +Editor.GotoLine.dialog.title=Go to Line +Editor.GotoLine.dialog.message=Enter line number: +Editor.GotoLine.dialog.invalid_input=Invalid line number +Editor.GotoLine.dialog.invalid_range=Line number out of range + +Editor.NextError.label= Go To Next Error +Editor.PreviousError.label=Go To Previous Error +Editor.NextError.tooltip= Jump to next error marker +Editor.PreviousError.tooltip=Jump to previous error marker + + +Editor.error.no_provider=Text editor does not have a document provider +Editor.error.save.title=Save Problems +Editor.error.save.message=Internal error: +Editor.error.revert.title=Problems While Reverting to Saved State +Editor.error.revert.message=Internal error: +Editor.error.no_input=Unable to read text editor input +Editor.error.invalid_input=Invalid text editor input + +CEditorPreferencePage.description= C Editor Preferences + +# ------- OpenIncludeDeclarationAction------------ + +OpenIncludeAction.label=&Open +OpenIncludeAction.tooltip=Open the Selected Include in the Editor +OpenIncludeAction.description=Open the selected include in the editor +OpenIncludeAction.dialog.title=Open Include +OpenIncludeAction.dialog.message=Select the file to open + +# ------- SearchForReferencesAction --------------- +SearchForReferencesAction.label=Reference&s +SearchForReferencesAction.tooltip=Search for References to Name in Workspace +SearchForReferencesAction.description=Searches for references to name in workspace + +# ------- LexicalSortingAction------------ + +LexicalSortingAction.label=Sort +LexicalSortingAction.description=Sorts the elements in the outliner +LexicalSortingAction.tooltip=Sort +LexicalSortingAction.tooltip.on=Do Not Sort +LexicalSortingAction.tooltip.off=Sort + +# ------- ClearOutputAction------------ +ClearOutputAction.label=Clea&r Console +ClearOutputAction.tooltip=Clear Console + +# ------- New menu items to overwrite superclass ---------- +CreateFileAction.text = &File +CreateFolderAction.text = F&older \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CStatusConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CStatusConstants.java new file mode 100644 index 00000000000..f333bb96704 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CStatusConstants.java @@ -0,0 +1,30 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Defines status codes relevant to the C UI plug-in. When a + * Core exception is thrown, it contain a status object describing + * the cause of the exception. The status objects originating from the + * C UI plug-in use the codes defined in this interface. + */ +public class CStatusConstants { + + // Prevent instantiation + private CStatusConstants() { + } + + /** Status code describing an internal error */ + public static final int INTERNAL_ERROR= 1; + + /** + * Status constant indicating that an exception occured on + * storing or loading templates. + */ + public static final int TEMPLATE_IO_EXCEPTION = 2; + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIException.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIException.java new file mode 100644 index 00000000000..0c2462b1a26 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIException.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; + +/** + * An exception to wrap a status. This is necessary to use the core's IRunnableWithProgress + * support + */ + +public class CUIException extends CoreException { + + public CUIException(IStatus status) { + super(status); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIStatus.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIStatus.java new file mode 100644 index 00000000000..f7d1cb64563 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CUIStatus.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Convenience class for error exceptions thrown inside JavaUI plugin. + */ +public class CUIStatus extends Status { + + public CUIStatus(int code, String message, Throwable throwable) { + super(IStatus.ERROR, CPlugin.getPluginId(), code, message, throwable); + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CWorkbenchAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CWorkbenchAdapter.java new file mode 100644 index 00000000000..788ff6f0f99 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CWorkbenchAdapter.java @@ -0,0 +1,60 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.model.IWorkbenchAdapter; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IParent; + +/** + * An imlementation of the IWorkbenchAdapter for CElements. + */ +public class CWorkbenchAdapter implements IWorkbenchAdapter { + + private static final Object[] fgEmptyArray= new Object[0]; + + /** + * @see IWorkbenchAdapter#getChildren + */ + public Object[] getChildren(Object o) { + if (o instanceof IParent) { + Object[] members= ((IParent)o).getChildren(); + if (members != null) { + return members; + } + } + return fgEmptyArray; + } + + /** + * @see IWorkbenchAdapter#getImageDescriptor + */ + public ImageDescriptor getImageDescriptor(Object object) { + return null; + } + + /** + * @see IWorkbenchAdapter#getLabel + */ + public String getLabel(Object o) { + if (o instanceof ICElement) { + return ((ICElement)o).getElementName(); + } + return null; + } + + /** + * @see IWorkbenchAdapter#getParent + */ + public Object getParent(Object o) { + if (o instanceof ICElement) { + return ((ICElement)o).getParent(); + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ClearConsoleAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ClearConsoleAction.java new file mode 100644 index 00000000000..50394ec5d46 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ClearConsoleAction.java @@ -0,0 +1,38 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.Action; + +import org.eclipse.ui.help.WorkbenchHelp; + + +/** + * Clears the output of the selected launches + */ +public class ClearConsoleAction extends Action { + + + private BuildConsoleView fConsoleView; + + + public ClearConsoleAction(BuildConsoleView view) { + super(CPlugin.getResourceString("ClearOutputAction.label")); + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_CLEAR_CONSOLE); + fConsoleView= view; + setToolTipText(CPlugin.getResourceString("ClearOutputAction.tooltip")); + WorkbenchHelp.setHelp( + this, + new Object[] { ICHelpContextIds.CLEAR_CONSOLE_ACTION }); + } + + /** + * @see Action + */ + public void run() { + fConsoleView.clear(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ErrorTickAdornmentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ErrorTickAdornmentProvider.java new file mode 100644 index 00000000000..8e516685e78 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ErrorTickAdornmentProvider.java @@ -0,0 +1,138 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; + +import org.eclipse.ui.texteditor.MarkerAnnotation; +import org.eclipse.ui.texteditor.MarkerUtilities; + +public class ErrorTickAdornmentProvider implements IAdornmentProvider { + + private static final int ERRORTICK_WARNING= CElementImageProvider.OVERLAY_WARNING; + private static final int ERRORTICK_ERROR= CElementImageProvider.OVERLAY_ERROR; + + /* + * @see IAdornmentProvider#computeAdornmentFlags(Object, int) + */ + public int computeAdornmentFlags(Object obj) { + try { + if (obj instanceof ICElement) { + ICElement element= (ICElement) obj; + if (!element.exists()) { + // @@@ Not relevant right now... + //return 0; + } + + int type= element.getElementType(); + switch (type) { + case ICElement.C_PROJECT: + case ICElement.C_FOLDER: + return getErrorTicksFromMarkers(element.getCorrespondingResource(), IResource.DEPTH_INFINITE, null); + case ICElement.C_FILE: + return getErrorTicksFromMarkers(element.getCorrespondingResource(), IResource.DEPTH_ONE, null); + case ICElement.C_FUNCTION: + case ICElement.C_CLASS: + case ICElement.C_UNION: + case ICElement.C_STRUCT: + case ICElement.C_VARIABLE: + case ICElement.C_METHOD: + ITranslationUnit tu= (ITranslationUnit) ((ISourceReference)element).getTranslationUnit(); + if (tu != null && tu.exists()) { + // I assume that only source elements in compilation unit can have markers + ISourceRange range= ((ISourceReference)element).getSourceRange(); + return getErrorTicksFromMarkers(tu.getCorrespondingResource(), IResource.DEPTH_ONE, range); + } + default: + } + } else if (obj instanceof IResource) { + return getErrorTicksFromMarkers((IResource) obj, IResource.DEPTH_INFINITE, null); + } + } catch (CoreException e) { + CPlugin.log(e); + } + return 0; + } + + /* + * @see IAdornmentProvider#dispose() + */ + public void dispose() { + } + + private int getErrorTicksFromMarkers(IResource res, int depth, ISourceRange range) throws CoreException { + // Trying to call findMarkers() on non existing resources will throw an exception + // findMarkers() --> CoreException - if this method fails. + // Reasons include: + // This resource does not exist. + // This resource is a project that is not open. + if (res == null || !res.exists()) { // for elements in archives + return 0; + } + int info= 0; + + IMarker[] markers= res.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, depth); + if (markers != null) { + for (int i= 0; i < markers.length && (info != ERRORTICK_ERROR); i++) { + IMarker curr= markers[i]; + if (range == null || isMarkerInRange(curr, range)) { + int priority= curr.getAttribute(IMarker.SEVERITY, -1); + if (priority == IMarker.SEVERITY_WARNING) { + info= ERRORTICK_WARNING; + } else if (priority == IMarker.SEVERITY_ERROR) { + info= ERRORTICK_ERROR; + } + } + } + } + return info; + } + + private boolean isMarkerInRange(IMarker marker, ISourceRange range) throws CoreException { + if (marker.isSubtypeOf(IMarker.TEXT)) { + int pos= marker.getAttribute(IMarker.CHAR_START, -1); + int offset= range.getStartPos(); + if(pos == -1) { + int line= MarkerUtilities.getLineNumber(marker); + if (line >= 0) { + return (line >= range.getStartLine() && line <= range.getEndLine()); + } + + } + return (offset <= pos && offset + range.getLength() > pos); + } + return false; + } + + + private IMarker isAnnotationInRange(IAnnotationModel model, Annotation annot, ISourceRange range) throws CoreException { + if (annot instanceof MarkerAnnotation) { + IMarker marker= ((MarkerAnnotation)annot).getMarker(); + if (marker.exists() && marker.isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER)) { + Position pos= model.getPosition(annot); + if (pos.overlapsWith(range.getStartPos(), range.getLength())) { + return marker; + } + } + } + + return null; + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IAdornmentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IAdornmentProvider.java new file mode 100644 index 00000000000..782e77836f6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IAdornmentProvider.java @@ -0,0 +1,27 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * @since 1.0 + */ +public interface IAdornmentProvider { + + /** + * Computes the adornment flags for the given element. + * Flags defined in JavaElementImageProvider. + */ + int computeAdornmentFlags(Object element); + + + /** + * Called when the parent label provider is disposed + */ + void dispose(); + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICElementPropertyConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICElementPropertyConstants.java new file mode 100644 index 00000000000..093bd15e59a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICElementPropertyConstants.java @@ -0,0 +1,49 @@ +package org.eclipse.cdt.internal.ui; + +/** + * This interface documents the property constants used by the ICElement + * property source. + */ + +public interface ICElementPropertyConstants { + /** + * The ICElement property key for elf cpu. + */ + public static final String P_ELF_CPU = "elf_cpu"; + + /** + * The ICElement property key for elf text. + */ + public static final String P_ELF_TEXT = "text"; + + /** + * The ICElement property key for elf data. + */ + public static final String P_ELF_DATA = "data"; + + /** + * The ICElement property key for elf bss. + */ + public static final String P_ELF_BSS = "bss"; + + /** + * The ICElement property key for elf bss. + */ + public static final String P_ELF_HAS_DEBUG = "debug"; + + /** + * The ICElement property key for elf soname. + */ + public static final String P_ELF_SONAME = "soname"; + + /** + * The ICElement property key for elf type. + */ + public static final String P_ELF_TYPE = "type"; + + /** + * The ICElement property key for elf type. + */ + public static final String P_ELF_NEEDED = "needed"; + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java new file mode 100644 index 00000000000..9bd6404e3dc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java @@ -0,0 +1,38 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Help context ids for the c ui. + *

+ * This interface contains constants only; it is not intended to be implemented + * or extended. + *

+ * + */ +public interface ICHelpContextIds { + public static final String PREFIX= CPlugin.PLUGIN_ID + "."; + + // Wizard pages + public static final String NEW_CPROJECT_WIZARD_PAGE= PREFIX + "new_cproject_wizard_page_context"; + public static final String NEW_LAUNCH_WIZARD_PAGE= PREFIX + "new_launch_wizard_page_context"; + + + // Preference/property pages + public static final String C_PREF_PAGE= PREFIX + "new_c_pref_page_context"; + public static final String C_EDITOR_PREF_PAGE= PREFIX + "new_c_editor_pref_page_context"; + public static final String TEMPLATE_PREFERENCE_PAGE= PREFIX + "new_c_templates_pref_page_context"; + public static final String LAUNCH_PROPERTY_PAGE= PREFIX + "new_launch_property_page_context"; + public static final String PROJECT_PROPERTY_PAGE= PREFIX + "new_project_property_page_context"; + + public static final String PROJ_CONF_BLOCK= PREFIX + "new_proj_conf_block_context"; + + // Console view + public static final String CLEAR_CONSOLE_ACTION= PREFIX + "clear_console_action_context"; + public static final String CLEAR_CONSOLE_VIEW= PREFIX + "clear_console_view_context"; + + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IContextMenuConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IContextMenuConstants.java new file mode 100644 index 00000000000..1651004a28b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/IContextMenuConstants.java @@ -0,0 +1,102 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.ui.IWorkbenchActionConstants; + +/** + * Constants for menu groups used in context menus for C views and editors. + *

+ * This interface declares constants only; it is not intended to be implemented. + *

+ */ +public interface IContextMenuConstants { + + + /** + * Pop-up menu: name of group for goto actions (value "group.open"). + *

+ * Examples for open actions are: + *

+ *

+ */ + public static final String GROUP_GOTO= "group.goto"; //$NON-NLS-1$ + /** + * Pop-up menu: name of group for open actions (value "group.open"). + *

+ * Examples for open actions are: + *

+ *

+ */ + public static final String GROUP_OPEN= "group.open"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for show actions (value "group.show"). + *

+ * Examples for show actions are: + *

+ *

+ */ + public static final String GROUP_SHOW= "group.show"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for new actions (value "group.new"). + *

+ * Examples for new actions are: + *

+ *

+ */ + public static final String GROUP_NEW= "group.new"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for build actions (value "group.build"). + */ + public static final String GROUP_BUILD= "group.build"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for reorganize actions (value "group.reorganize"). + */ + public static final String GROUP_REORGANIZE= IWorkbenchActionConstants.GROUP_REORGANIZE; + + /** + * Pop-up menu: name of group for code generation or refactoring actions ( + * value "group.generate"). + */ + public static final String GROUP_GENERATE= "group.generate"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for search actions (value "group.search"). + */ + public static final String GROUP_SEARCH= "group.search"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for additional actions (value "group.additions"). + */ + public static final String GROUP_ADDITIONS= "additions"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for viewer setup actions (value "group.viewerSetup"). + */ + public static final String GROUP_VIEWER_SETUP= "group.viewerSetup"; //$NON-NLS-1$ + + /** + * Pop-up menu: name of group for properties actions (value "group.properties"). + */ + public static final String GROUP_PROPERTIES= "group.properties"; //$NON-NLS-1$ +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/PluginAdapterFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/PluginAdapterFactory.java new file mode 100644 index 00000000000..4c42e1cef21 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/PluginAdapterFactory.java @@ -0,0 +1,41 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.resources.*; +import org.eclipse.cdt.internal.CCorePlugin; +import org.eclipse.core.runtime.IAdapterFactory; + +//import org.eclipse.cdt.core.model.ICElement; +//import org.eclipse.cdt.core.model.CCore; + +public class PluginAdapterFactory implements IAdapterFactory { + + private static Class[] PROPERTIES= new Class[] { + ICPlugin.class + }; + + //private static CCore fgCElementFactory= CCore.getDefault(); + + /** + * @see IAdapterFactory#getAdapterList + */ + public Class[] getAdapterList() { + return PROPERTIES; + } + + /** + * @see IAdapterFactory#getAdapter + */ + public Object getAdapter(Object element, Class key) { + if (ICPlugin.class.equals(key)) { + if (element instanceof CCorePlugin) { + return CPlugin.getDefault(); + } + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ResourceAdapterFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ResourceAdapterFactory.java new file mode 100644 index 00000000000..e9f674fa2e4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ResourceAdapterFactory.java @@ -0,0 +1,57 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IAdapterFactory; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CoreModel; + +public class ResourceAdapterFactory implements IAdapterFactory { + + private static Class[] PROPERTIES= new Class[] { + ICElement.class + }; + + //private static CElementFactory celementFactory= new CElementFactory(); + private static CoreModel celementFactory= CoreModel.getDefault(); + + /** + * @see IAdapterFactory#getAdapterList + */ + public Class[] getAdapterList() { + return PROPERTIES; + } + + /** + * @see IAdapterFactory#getAdapter + */ + public Object getAdapter(Object element, Class key) { + if (ICElement.class.equals(key)) { + //try { + if (element instanceof IFile) { + return celementFactory.create((IFile)element); + } else if (element instanceof IFolder) { + return celementFactory.create((IFolder)element); + } else if (element instanceof IProject) { + return celementFactory.create((IProject)element); + } else if (element instanceof IWorkspaceRoot) { + return celementFactory.create((IWorkspaceRoot)element); + } else if (element instanceof IResource) { + return celementFactory.create((IResource)element); + } + //} catch (CoreException e) { + // CPlugin.getDefault().getLog().log(e.getStatus()); + //} + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/StandardCElementLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/StandardCElementLabelProvider.java new file mode 100644 index 00000000000..199e593727e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/StandardCElementLabelProvider.java @@ -0,0 +1,90 @@ +package org.eclipse.cdt.internal.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * CElementLabelProvider that respects settings from the Appearance preference page. + * Triggers a viewer update when a preference changes. + */ +public class StandardCElementLabelProvider extends CElementLabelProvider implements IPropertyChangeListener { + + public final static int DEFAULT_TEXTFLAGS= 0; //CElementLabels.ROOT_VARIABLE | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_APP_RETURNTYPE; + public final static int DEFAULT_IMAGEFLAGS= CElementImageProvider.OVERLAY_ICONS; + + private int fTextFlagMask; + private int fImageFlagMask; + + /** + * Constructor for StandardCElementLabelProvider. + * @see CElementLabelProvider#CElementLabelProvider + */ + public StandardCElementLabelProvider(int textFlags, int imageFlags, IAdornmentProvider[] adormentProviders) { + super(textFlags, imageFlags, adormentProviders); + initMasks(); + CPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); + } + + /** + * Creates a StandardCElementLabelProvider with DEFAULT_TEXTFLAGS, DEFAULT_IMAGEFLAGS + * and the ErrorTickAdornmentProvider. + */ + public StandardCElementLabelProvider() { + this(DEFAULT_TEXTFLAGS, DEFAULT_IMAGEFLAGS, new IAdornmentProvider[] { new ErrorTickAdornmentProvider() }); + } + + private void initMasks() { + fTextFlagMask= -1; + /* if (!AppearancePreferencePage.showMethodReturnType()) { + fTextFlagMask ^= JavaElementLabels.M_APP_RETURNTYPE; + } + if (!AppearancePreferencePage.isCompressingPkgNameInPackagesView()) { + fTextFlagMask ^= JavaElementLabels.P_COMPRESSED; + } */ + + fImageFlagMask= -1; + } + + /* + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + //String property= event.getProperty(); + /* if (property.equals(AppearancePreferencePage.PREF_METHOD_RETURNTYPE) + || property.equals(AppearancePreferencePage.PREF_OVERRIDE_INDICATOR) + || property.equals(AppearancePreferencePage.PREF_PKG_NAME_PATTERN_FOR_PKG_VIEW)) { + initMasks(); + LabelProviderChangedEvent lpEvent= new LabelProviderChangedEvent(this, null); // refresh all + fireLabelProviderChanged(lpEvent); + } */ + } + + /* + * @see IBaseLabelProvider#dispose() + */ + public void dispose() { + CPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); + super.dispose(); + } + + /* + * @see JavaUILabelProvider#getImageFlags() + */ + public int getImageFlags() { + return super.getImageFlags() & fImageFlagMask; + } + + /* + * @see JavaUILabelProvider#getTextFlags() + */ + public int getTextFlags() { + return super.getTextFlags() & fTextFlagMask; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/AddIncludeOperation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/AddIncludeOperation.java new file mode 100644 index 00000000000..bc46fea7f6f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/codemanipulation/AddIncludeOperation.java @@ -0,0 +1,151 @@ +package org.eclipse.cdt.internal.ui.codemanipulation; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.internal.ui.CFileElementWorkingCopy; +import org.eclipse.cdt.internal.ui.editor.CContentOutlinePage; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.CEditorMessages; +import org.eclipse.cdt.ui.IRequiredInclude; +import java.util.ArrayList; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Add includes to a translation unit. + * The input is an array of full qualified type names. No elimination of unnecessary + * includes is not done. Dublicates are eliminated. + * If the translation unit is open in an editor, be sure to pass over its working copy. + */ +public class AddIncludeOperation extends WorkspaceModifyOperation { + + private CFileElementWorkingCopy fTranslationUnit; + private IRequiredInclude[] fIncludes; + private boolean fDoSave; + private ITextEditor fEditor; + + private IInclude[] fAddedIncludes; + + /** + * Generate import statements for the passed java elements + * Elements must be of type IType (-> single import) or IPackageFragment + * (on-demand-import). Other JavaElements are ignored + */ + public AddIncludeOperation(ITextEditor ed, CFileElementWorkingCopy tu, IRequiredInclude[] includes, boolean save) { + super(); + fEditor = ed; + fIncludes= includes; + fTranslationUnit= tu; + fAddedIncludes= null; + fDoSave= save; + } + + public void execute(IProgressMonitor monitor) throws CoreException { + try { + ArrayList toAdd = new ArrayList(); + + if (monitor == null) { + monitor= new NullProgressMonitor(); + } + + monitor.beginTask(CEditorMessages.getString("AddIncludesOperation.description"), 2); //$NON-NLS-1$ + + ICElement root; + // Look in content outline + if(fEditor instanceof CEditor) { + CContentOutlinePage outline = ((CEditor)fEditor).getOutlinePage(); + root = outline.getRoot(); + } else { + root = fTranslationUnit; + } + if (root != null && root instanceof IParent && ((IParent)root).hasChildren()) { + //// Get children of tu + // Build list of include statement + //fTranslationUnit.update(); + //if(fTranslationUnit.hasChildren()) { + ICElement lastInclude = null; + ICElement[] elements = ((IParent)root).getChildren(); + + for(int j = 0; j < fIncludes.length; j++) { + //System.out.println("Comparing to " + fIncludes[j].getIncludeName()); + toAdd.add(fIncludes[j]); + } + + for(int i = 0; i < elements.length; i++) { + if(elements[i].getElementType() == ICElement.C_INCLUDE) { + lastInclude = elements[i]; + //System.out.println("Element " + elements[i].getElementName() + "sys " + ((IInclude)elements[i]).isStandard()); + for(int j = 0; j < toAdd.size(); j++) { + //System.out.println("Comparing to " + ((IRequiredInclude)toAdd.get(j)).getIncludeName()); + if(elements[i].getElementName().equals(((IRequiredInclude)toAdd.get(j)).getIncludeName())) { + toAdd.remove(j); + } + } + } + } + + if(toAdd.size() > 0) { + // So we have our list. Now insert. + StringBuffer insert = new StringBuffer(""); + for(int j = 0; j < toAdd.size(); j++) { + insert.append("#include <" + ((IRequiredInclude)toAdd.get(j)).getIncludeName() + ">\n"); + } + int pos; + + if(lastInclude != null) { + ISourceRange range = ((IInclude)lastInclude).getSourceRange(); + pos = range.getStartPos() + range.getLength(); + } else { + pos = 0; + } + + IDocument document = fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + try { + // Now find the next newline and insert after that + if(pos > 0) { + while(document.getChar(pos) != '\n') pos++; + if(document.getChar(pos) == '\r') pos++; + pos++; + } + document.replace(pos, 0, insert.toString()); + } catch (BadLocationException e) {} + } + + } + + + /*for (int i= 0; i < nImports; i++) { + IJavaElement imp= fIncludes[i]; + if (imp instanceof IType) { + IType type= (IType)imp; + String packageName= type.getPackageFragment().getElementName(); + impStructure.addImport(packageName, type.getElementName()); + } else if (imp instanceof IPackageFragment) { + String packageName= ((IPackageFragment)imp).getElementName(); + impStructure.addImport(packageName, "*"); //$NON-NLS-1$ + } + } */ + monitor.worked(1); + //fAddedImports= impStructure.create(fDoSave, null); + monitor.worked(1); + } finally { + monitor.done(); + } + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CContentViewerCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CContentViewerCreator.java new file mode 100644 index 00000000000..bcaa258415f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CContentViewerCreator.java @@ -0,0 +1,27 @@ +package org.eclipse.cdt.internal.ui.compare; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.IViewerCreator; + + +import org.eclipse.jface.viewers.Viewer; + + +/** + * Required when creating a CMergeViewer from the plugin.xml file. + */ +public class CContentViewerCreator implements IViewerCreator { + + public Viewer createViewer(Composite parent, CompareConfiguration mp) { + return new CMergeViewer(parent, SWT.NULL, mp); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CMergeViewer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CMergeViewer.java new file mode 100644 index 00000000000..ee83ca9c468 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CMergeViewer.java @@ -0,0 +1,53 @@ +package org.eclipse.cdt.internal.ui.compare; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; + + +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.contentmergeviewer.ITokenComparator; +import org.eclipse.compare.contentmergeviewer.TextMergeViewer; +import org.eclipse.compare.internal.TokenComparator; + + +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.source.SourceViewer; + +public class CMergeViewer extends TextMergeViewer { + + private static final String TITLE= "CMergeViewer.title"; + + + public CMergeViewer(Composite parent, int styles, CompareConfiguration mp) { + super(parent, styles, mp); + } + + public String getTitle() { + return CPlugin.getResourceString(TITLE); + } + + + protected ITokenComparator createTokenComparator(String s) { + return new TokenComparator(s); + } + + protected IDocumentPartitioner getDocumentPartitioner() { + return CPlugin.getDefault().getTextTools().createDocumentPartitioner(); + } + + protected void configureTextViewer(TextViewer textViewer) { + if (textViewer instanceof SourceViewer) { + CTextTools tools= CPlugin.getDefault().getTextTools(); + ((SourceViewer)textViewer).configure(new CSourceViewerConfiguration(tools, null)); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java new file mode 100644 index 00000000000..092594f25a6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/compare/CStructureCreator.java @@ -0,0 +1,308 @@ +package org.eclipse.cdt.internal.ui.compare; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.eclipse.swt.graphics.Image; + +import org.eclipse.compare.IEditableContent; +import org.eclipse.compare.IStreamContentAccessor; +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; +import org.eclipse.compare.structuremergeviewer.IDiffContainer; +import org.eclipse.compare.structuremergeviewer.IStructureComparator; +import org.eclipse.compare.structuremergeviewer.IStructureCreator; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.core.DocumentInputStream; +import org.eclipse.cdt.internal.parser.CStructurizer; +import org.eclipse.cdt.internal.parser.IStructurizerCallback; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +/** + * + */ +public class CStructureCreator implements IStructureCreator { + + private static final String NAME= "CStructureCreator.name"; + + public CStructureCreator() { + } + + /** + * @see IStructureCreator#getTitle + */ + public String getName() { + return CPlugin.getResourceString(NAME); + } + + /** + * @see IStructureCreator#getStructure + */ + public IStructureComparator getStructure(Object input) { + + String s= null; + if (input instanceof IStreamContentAccessor) { + try { + s= readString(((IStreamContentAccessor) input).getContents()); + } catch(CoreException ex) { + } + } + + Document doc= new Document(s != null ? s : ""); + + CNode root= new CNode(null, ICElement.C_FILE, "root", doc, 0, 0); + + DocumentInputStream is= new DocumentInputStream(doc); + IStructurizerCallback callback= new CNodeTreeConstructor(root, doc); + try { + CStructurizer.getCStructurizer().parse(callback, is); + } catch (NodeConstructorError e) { + System.out.println("Parse error: " + e); + return null; + } catch (IOException e) { + return null; + } + + return root; + } + + /** + * @see IStructureCreator#canSave + */ + public boolean canSave() { + return true; + } + + /** + * @see IStructureCreator#locate + */ + public IStructureComparator locate(Object path, Object source) { + return null; + } + + /** + * @see IStructureCreator#canRewriteTree + */ + public boolean canRewriteTree() { + return false; + } + + /** + * @see IStructureCreator#rewriteTree + */ + public void rewriteTree(Differencer differencer, IDiffContainer root) { + } + + /** + * @see IStructureCreator#save + */ + public void save(IStructureComparator structure, Object input) { + if (input instanceof IEditableContent && structure instanceof CNode) { + IDocument doc= ((CNode)structure).getDocument(); + IEditableContent bca= (IEditableContent) input; + String c= doc.get(); + bca.setContent(c.getBytes()); + } + } + + /** + * @see IStructureCreator#getContents + */ + public String getContents(Object node, boolean ignoreWhitespace) { + if (node instanceof IStreamContentAccessor) { + IStreamContentAccessor sca= (IStreamContentAccessor) node; + try { + return readString(sca.getContents()); + } catch (CoreException ex) { + } + } + return null; + } + + private static class CNode extends DocumentRangeNode implements ITypedElement { + + private String fImageKey; + private CNode fParent; + private int fCode; + + public CNode(CNode parent, int type, String id, IDocument doc, int start, int length) { + super(type, id, doc, start, length); + fCode = type; + fImageKey= CPluginImages.IMG_OBJS_STRUCT; + fParent= parent; + } + + /** + * Returns the type code of this node. + * The type code is uninterpreted client data which can be set in the constructor. + * + * @return the type code of this node + */ + public int getTypeCode() { + return fCode; + } + + public void setTypeCode(int code) { + fCode = code; + } + + public CNode getParent() { + return fParent; + } + + /** + * @see ITypedInput#getName + */ + public String getName() { + return getId(); + } + + /** + * @see ITypedInput#getType + */ + public String getType() { + return "c2"; + } + + /** + * @see ITypedInput#getImage + */ + public Image getImage() { + if (fImageKey != null) { + return CPluginImages.get(fImageKey); + } + return null; + } + }; + + private static class NodeConstructorError extends Error { + } + + private static class CNodeTreeConstructor implements IStructurizerCallback { + + private CNode fRoot; + private CNode fCurrent; + + private IDocument fDocument; + + public CNodeTreeConstructor(CNode root, IDocument doc) { + fRoot= root; + fCurrent= root; + fDocument= doc; + } + + private CNode getParent(CNode node) { + CNode parent= node.getParent(); + if (parent == null) { + throw new NodeConstructorError(); + } + return parent; + } + + private final int fixLength(int startPos, int endPos) { + if (endPos < startPos) { + return 0; + } else { + return endPos - startPos + 1; + } + } + + + public void includeDecl(String name, int startPos, int endPos, int startLine, int endLine) { + CNode node= new CNode(fRoot, ICElement.C_INCLUDE, name, fDocument, startPos, fixLength(startPos, endPos)); + fRoot.addChild(node); + } + + public void defineDecl(String name, int startPos, int endPos, int startLine, int endLine) { + CNode node= new CNode(fRoot, ICElement.C_MACRO, name, fDocument, startPos, fixLength(startPos, endPos)); + fRoot.addChild(node); + } + + public void functionDeclBegin(String name, int nameStartPos, int nameEndPos, + int declStartPos, int startLine, int type, int modifiers) { + CNode node= new CNode(fCurrent, ICElement.C_FUNCTION, name, fDocument, declStartPos, 0); + fCurrent.addChild(node); + fCurrent= node; + } + + public void functionDeclEnd(int declEndPos, int endLine, boolean prototype) { + if(prototype) { + fCurrent.setTypeCode(ICElement.C_FUNCTION_DECLARATION); + } + Position p= fCurrent.getRange(); + fCurrent.setLength(fixLength(p.getOffset(), declEndPos)); + fCurrent= getParent(fCurrent); + } + + public void fieldDecl(String name, int nameStartPos, int nameEndPos, int declStartPos, + int declEndPos, int startLine, int endLine, int modifiers) { + CNode node= new CNode(fCurrent, ICElement.C_FIELD, name, fDocument, declStartPos, fixLength(declStartPos, declEndPos)); + fCurrent.addChild(node); + } + + public void structDeclBegin(String name, int kind, int nameStartPos, int nameEndPos, + int declStartPos, int startLine, int modifiers) { + CNode node= new CNode(fCurrent, kind, name, fDocument, declStartPos, 0); + fCurrent.addChild(node); + fCurrent= node; + } + + public void structDeclEnd(int declEndPos, int endLine) { + Position p= fCurrent.getRange(); + fCurrent.setLength(fixLength(p.getOffset(), declEndPos)); + fCurrent= getParent(fCurrent); + } + + public void superDecl(String name) { + } + + public void reportError(Throwable throwable) { + throw new NodeConstructorError(); + } + } + + /** + * Returns null if an error occurred. + */ + private static String readString(InputStream is) { + if (is == null) + return null; + BufferedReader reader= null; + try { + StringBuffer buffer= new StringBuffer(); + char[] part= new char[2048]; + int read= 0; + reader= new BufferedReader(new InputStreamReader(is)); + + while ((read= reader.read(part)) != -1) + buffer.append(part, 0, read); + + return buffer.toString(); + + } catch (IOException ex) { + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex) { + } + } + } + return null; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CElementFilters.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CElementFilters.java new file mode 100644 index 00000000000..28e29cefda8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CElementFilters.java @@ -0,0 +1,132 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.util.StringMatcher; + +/** + * The FiltersContent provides the elements for use by the list dialog + * for selecting the patterns to apply. + */ +public class CElementFilters { + static List definedFilters = null; + static List defaultFilters = null; + static StringMatcher [] matchers = null; + static String FILTERS_TAG= "CElementFilters"; //$NON-NLS-1$ + static String COMMA_SEPARATOR = ","; //$NON-NLS-1$ + + /** + * Returns the filters which are enabled by default. + * + * @return a list of strings + */ + public static List getDefaultFilters() { + if (defaultFilters == null) { + readFilters(); + } + return defaultFilters; + } + + /** + * Returns the filters currently defined for the workbench. + */ + public static List getDefinedFilters() { + if (definedFilters == null) { + // Overide the default by the user preference + CPlugin plugin = CPlugin.getDefault(); + String storedPatterns= plugin.getPropertyStore().getString(FILTERS_TAG); + + if (storedPatterns.length() > 0) { + StringTokenizer entries = new StringTokenizer(storedPatterns, COMMA_SEPARATOR); + definedFilters = new ArrayList(); + + while (entries.hasMoreElements()) { + String nextToken = entries.nextToken(); + definedFilters.add(nextToken); + } + } else { + readFilters(); + } + } + return definedFilters; + } + + public static StringMatcher [] getMatchers() { + if (matchers == null) { + List list = getDefinedFilters(); + matchers = new StringMatcher[list.size()]; + for (int i = 0; i < matchers.length; i++) { + matchers[i] = new StringMatcher((String)(list.get(i)), true, false); + } + } + return matchers; + } + + /** + * Define new Patterns for the Duration of the session. + */ + public static void setPatterns(String[] newPatterns) { + //System.out.println ("SetPatterns call"); + matchers = new StringMatcher[newPatterns.length]; + for (int i = 0; i < newPatterns.length; i++) { + //System.out.println ("Patterns " + newPatterns[i]); + matchers[i] = new StringMatcher(newPatterns[i], true, false); + } + //CElementFactory.getDefault().refreshDeadBranchParents(); + } + + + public static boolean match(String name) { + StringMatcher [] m = getMatchers(); + if (m == null) + return false; + //System.out.println ("Pattern " + name); + for (int i = 0; i < m.length; i++) { + if (m[i].match(name)) { + //System.out.println ("Match " + name); + return true; + } + } + return false; + } + + private CElementFilters() { + } + /** + * Reads the filters currently defined for the workbench. + */ + static void readFilters() { + definedFilters = new ArrayList(); + defaultFilters = new ArrayList(); + CPlugin plugin = CPlugin.getDefault(); + if (plugin != null) { + IExtensionPoint extension = plugin.getDescriptor().getExtensionPoint(FILTERS_TAG); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for(int i = 0; i < extensions.length; i++){ + IConfigurationElement [] configElements = extensions[i].getConfigurationElements(); + for(int j = 0; j < configElements.length; j++){ + String pattern = configElements[j].getAttribute("pattern"); //$NON-NLS-1$ + if (pattern != null) + definedFilters.add(pattern); + String selected = configElements[j].getAttribute("selected"); //$NON-NLS-1$ + if (selected != null && selected.equalsIgnoreCase("true")) //$NON-NLS-1$ + defaultFilters.add(pattern); + } + } + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CLibFilter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CLibFilter.java new file mode 100644 index 00000000000..64c471e9c3c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CLibFilter.java @@ -0,0 +1,40 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import org.eclipse.cdt.core.model.ILibraryReference; + +public class CLibFilter extends ViewerFilter { + private boolean showlib = true; + + public boolean getShowLibraries() { + return showlib; + } + + /* (non-Javadoc) + * Method declared on ViewerFilter. + */ + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof ILibraryReference) { + return showlib; + } + return true; + } + + public void setShowLibraries (boolean show) { + showlib = show; + } + + /** + * Creates a new library filter. + */ + public CLibFilter() { + super(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CPatternFilter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CPatternFilter.java new file mode 100644 index 00000000000..000fcceeceb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CPatternFilter.java @@ -0,0 +1,123 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.List; +import java.util.Vector; +import java.util.StringTokenizer; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; + +import org.eclipse.cdt.internal.ui.util.StringMatcher; +import org.eclipse.cdt.internal.ui.CPlugin; + +import org.eclipse.cdt.core.model.ICFolder; +import org.eclipse.cdt.core.model.ICProject; + +public class CPatternFilter extends ViewerFilter { + private String[] patterns; + private StringMatcher[] matchers; + + static String COMMA_SEPARATOR = ","; //$NON-NLS-1$ + static String FILTERS_TAG= "CElementFilters"; //$NON-NLS-1$ + + private void initializeFromPreferences() { + CPlugin plugin= CPlugin.getDefault(); + String storedPatterns= plugin.getPreferenceStore().getString(FILTERS_TAG); + + if (storedPatterns.length() == 0) { + List defaultFilters= FiltersContentProvider.getDefaultFilters(); + String[] patterns= new String[defaultFilters.size()]; + defaultFilters.toArray(patterns); + setPatterns(patterns); + return; + } + + //Get the strings separated by a comma and filter them from the currently + //defined ones + + List definedFilters = FiltersContentProvider.getDefinedFilters(); + + StringTokenizer entries = new StringTokenizer(storedPatterns, COMMA_SEPARATOR); + Vector patterns = new Vector(); + + while (entries.hasMoreElements()) { + String nextToken = entries.nextToken(); + if (definedFilters.indexOf(nextToken) > -1) + patterns.addElement(nextToken); + } + + //Convert to an array of Strings + String[] patternArray = new String[patterns.size()]; + patterns.toArray(patternArray); + setPatterns(patternArray); + } + + /** + * Gets the patterns for the receiver. Returns the cached values if there + * are any - if not look it up. + */ + public String[] getPatterns() { + if (patterns == null) { + initializeFromPreferences(); + } + return patterns; + } + + /** + * Sets the patterns to filter out for the receiver. + */ + public void setPatterns(String[] newPatterns) { + + patterns = newPatterns; + matchers = new StringMatcher[newPatterns.length]; + for (int i = 0; i < newPatterns.length; i++) { + //Reset the matchers to prevent constructor overhead + matchers[i] = new StringMatcher(newPatterns[i], true, false); + } + } + + + /** + * Return the currently configured StringMatchers. If there aren't any look + * them up. + */ + private StringMatcher[] getMatchers() { + if (matchers == null) + initializeFromPreferences(); + return matchers; + } + + /* (non-Javadoc) + * Method declared on ViewerFilter. + */ + public boolean select(Viewer viewer, Object parentElement, Object element) { + IResource resource = null; + if (element instanceof IResource) { + resource = (IResource) element; + } else if (element instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) element; + resource = (IResource) adaptable.getAdapter(IResource.class); + } + + // Only apply the rule for Projects and folders. + if (parentElement instanceof ICProject + || parentElement instanceof ICFolder) { + if (resource != null) { + String name = resource.getName(); + StringMatcher[] testMatchers = getMatchers(); + for (int i = 0; i < testMatchers.length; i++) { + if (testMatchers[i].match(name)) + return false; + } + } + } + return true; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java new file mode 100644 index 00000000000..54e3c4dd89a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CView.java @@ -0,0 +1,1178 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.actions.AddBookmarkAction; +import org.eclipse.ui.actions.CloseResourceAction; +import org.eclipse.ui.actions.CopyResourceAction; +import org.eclipse.ui.actions.CreateFileAction; +import org.eclipse.ui.actions.CreateFolderAction; +import org.eclipse.ui.actions.DeleteResourceAction; +import org.eclipse.ui.actions.MoveResourceAction; +import org.eclipse.ui.actions.NewWizardAction; +import org.eclipse.ui.actions.NewWizardMenu; +import org.eclipse.ui.actions.OpenFileAction; +import org.eclipse.ui.actions.OpenPerspectiveMenu; +import org.eclipse.ui.actions.OpenSystemEditorAction; +import org.eclipse.ui.actions.OpenWithMenu; +import org.eclipse.ui.actions.RefreshAction; +import org.eclipse.ui.actions.RenameResourceAction; +import org.eclipse.ui.dialogs.PropertyDialogAction; +import org.eclipse.ui.part.ISetSelectionTarget; +import org.eclipse.ui.part.PluginTransfer; +import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.views.framelist.BackAction; +import org.eclipse.ui.views.framelist.ForwardAction; +import org.eclipse.ui.views.framelist.FrameList; +import org.eclipse.ui.views.framelist.GoIntoAction; +import org.eclipse.ui.views.framelist.UpAction; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.IBinaryContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.resources.MakeUtil; +import org.eclipse.cdt.internal.ui.CContentProvider; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.StandardCElementLabelProvider; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.OpenIncludeAction; +import org.eclipse.cdt.internal.ui.makeview.MakeAction; +import org.eclipse.cdt.internal.ui.makeview.MakeTarget; +import org.eclipse.cdt.internal.ui.makeview.MakeTargetAction; +import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage; +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; + + + + +public class CView extends ViewPart implements IMenuListener, ISetSelectionTarget, + IPropertyChangeListener { + + ProblemTreeViewer viewer; + IMemento memento; + + // Actions for Menu context. + AddBookmarkAction addBookmarkAction; + //BuildAction buildAction; + //BuildAction rebuildAction; + MakeTargetAction makeTargetAction; + CopyResourceAction copyResourceAction; + DeleteResourceAction deleteResourceAction; + OpenFileAction openFileAction; + OpenSystemEditorAction openSystemEditorAction; + PropertyDialogAction propertyDialogAction; + RefreshAction refreshAction; + RenameResourceAction renameResourceAction; + MoveResourceAction moveResourceAction; + CreateFileAction createFileAction; + CreateFolderAction createFolderAction; + NewWizardAction newWizardAction; + CloseResourceAction closeResourceAction; + + // CElement action + OpenIncludeAction openIncludeAction; + + BackAction backAction; + ForwardAction forwardAction; + GoIntoAction goIntoAction; + UpAction upAction; + FrameList frameList; + CViewFrameSource frameSource; + + CPatternFilter patternFilter = new CPatternFilter (); + FilterSelectionAction patternFilterAction; + + CLibFilter clibFilter = new CLibFilter (); + ShowLibrariesAction clibFilterAction; + + + // Persistance tags. + static final String TAG_SELECTION= "selection"; //$NON-NLS-1$ + static final String TAG_EXPANDED= "expanded"; //$NON-NLS-1$ + static final String TAG_ELEMENT= "element"; //$NON-NLS-1$ + static final String TAG_PATH= "path"; //$NON-NLS-1$ + static final String TAG_VERTICAL_POSITION= "verticalPosition"; //$NON-NLS-1$ + static final String TAG_HORIZONTAL_POSITION= "horizontalPosition"; //$NON-NLS-1$ + static final String TAG_FILTERS = "filters"; //$NON-NLS-1$ + static final String TAG_FILTER = "filter"; //$NON-NLS-1$ + static final String TAG_SHOWLIBRARIES = "showLibraries"; //$NON-NLS-1$ + + private IPartListener partListener = new IPartListener() { + public void partActivated(IWorkbenchPart part) { + if (part instanceof IEditorPart) { + editorActivated((IEditorPart) part); + } + } + public void partBroughtToTop(IWorkbenchPart part) {} + public void partClosed(IWorkbenchPart part) {} + public void partDeactivated(IWorkbenchPart part) {} + public void partOpened(IWorkbenchPart part) {} + }; + + + public CView() { + super(); + } + + /** + * @see IWorkbenchPart#setFocus() + */ + public void setFocus() { + viewer.getTree().setFocus(); + //composite.setFocus (); + } + + /** + * Reveal and select the passed element selection in self's visual component + * @see ISetSelectionTarget#selectReveal() + */ + public void selectReveal(ISelection selection) { + IStructuredSelection ssel = convertSelectionToCElement(selection); + if (!ssel.isEmpty()) { + getResourceViewer().setSelection(ssel, true); + } + } + + private ITreeViewerListener expansionListener= new ITreeViewerListener() { + public void treeCollapsed(TreeExpansionEvent event) { + } + + public void treeExpanded(TreeExpansionEvent event) { + final Object element= event.getElement(); + if (element instanceof ICFile) { + //viewer.refresh (element); + Control ctrl= viewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) { + ctrl.getDisplay().asyncExec(new Runnable() { + public void run() { + Control ctrl= viewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) { + viewer.expandToLevel(element, 1); + } + } + }); + } + } + } + }; + + /** + * Handles double clicks in viewer. + * Opens editor if file double-clicked. + */ + private void handleDoubleClick(DoubleClickEvent event) { + IStructuredSelection s = (IStructuredSelection)event.getSelection(); + //Object element = s.getFirstElement(); + IAdaptable element = (IAdaptable)s.getFirstElement(); + IResource resource = null; + + if (element instanceof IAdaptable) { + resource = (IResource)((IAdaptable)element).getAdapter(IResource.class); + } + + if (resource == null) + return; + + //System.out.println ("Double click on " + element); + if (resource instanceof IFile) { + if (element instanceof ICElement) { + try { + EditorUtility.openInEditor((ICElement)element); + } catch (Exception e) { + } + } else { + openFileAction.selectionChanged(s); + openFileAction.run(); + } + } else { + if (viewer.isExpandable(element)) { + viewer.setExpandedState(element, !viewer.getExpandedState(element)); + } + } + } + + /** + * Handles key events in viewer. + */ + void handleKeyPressed(KeyEvent event) { + if (event.character == SWT.DEL + && event.stateMask == 0 && deleteResourceAction.isEnabled()) { + IStructuredSelection isel = deleteResourceAction.getStructuredSelection(); + Object[] array = isel.toArray(); + for (int i = 0; i < array.length; i++){ + if (array[i] instanceof IBinaryContainer + || array[i] instanceof IArchiveContainer) { + return; + } + } + deleteResourceAction.run(); + } + } + + + /* (non-Javadoc) + * Method declared on IViewPart. + */ + public void init(IViewSite site,IMemento memento) throws PartInitException { + super.init(site,memento); + this.memento = memento; + } + + void initFrameList() { + frameSource = new CViewFrameSource(this); + frameList = new FrameList(frameSource); + frameSource.connectTo(frameList); + } + + /** + * Answer the property defined by key. + */ + public Object getAdapter(Class key) { + if (key.equals(ISelectionProvider.class)) + return viewer; + return super.getAdapter(key); + } + + + /** + * Adds drag and drop support to the navigator. + */ + void initDragAndDrop() { + int ops = DND.DROP_COPY | DND.DROP_MOVE; + Transfer[] transfers = new Transfer[] {ResourceTransfer.getInstance(), + FileTransfer.getInstance(), PluginTransfer.getInstance()}; + viewer.addDragSupport(ops, transfers, new CViewDragAdapter((ISelectionProvider)viewer)); + viewer.addDropSupport(ops, transfers, new CViewDropAdapter(viewer)); + } + + /** + * Initializes the default preferences + */ + public static void initDefaults(IPreferenceStore store) { + store.setDefault(TAG_SHOWLIBRARIES, true); + } + + void initFilterFromPreferences() { + CPlugin plugin = CPlugin.getDefault(); + boolean show = plugin.getPreferenceStore().getBoolean(TAG_SHOWLIBRARIES); + getLibraryFilter().setShowLibraries(show); + } + + /** + * Create the KeyListener for doing the refresh on the viewer. + */ + void initRefreshKey() { + viewer.getControl().addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent event) { + if (event.keyCode == SWT.F5) { + refreshAction.selectionChanged( + (IStructuredSelection)viewer.getSelection()); + if (refreshAction.isEnabled()) + refreshAction.run(); + } + } + }); + } + + /** + * Handles selection changed in viewer. + * Updates global actions. + * Links to editor (if option enabled) + */ + void handleSelectionChanged(SelectionChangedEvent event) { + IStructuredSelection sel = (IStructuredSelection) event.getSelection(); + updateStatusLine(sel); + updateGlobalActions(sel); + goIntoAction.update(); + linkToEditor(sel); + } + + + /** + * @see ContentOutlinePage#createControl + */ + public void createPartControl (Composite parent) { + + viewer= new ProblemTreeViewer (parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + boolean showCUChildren= CPluginPreferencePage.showCompilationUnitChildren(); + viewer.setUseHashlookup (true); + viewer.setContentProvider(new CContentProvider (showCUChildren, true)); + viewer.setLabelProvider (new StandardCElementLabelProvider ()); + CPlugin.getDefault().getProblemMarkerManager().addListener(viewer); + CPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); + + // FIXME: Add Drag and Drop support. + initFrameList(); + initRefreshKey(); + updateTitle(); + initDragAndDrop(); + viewer.addFilter(patternFilter); + //viewer.addFilter(clibFilter); + viewer.setSorter(new CViewSorter ()); + // FIXME: Add different Sorting. + if(memento != null) + restoreFilters(); + else + initFilterFromPreferences(); + + viewer.setInput (CoreModel.getDefault().getCRoot()); + + MenuManager menuMgr= new MenuManager("#PopupMenu"); //$NON-NLS-1$ + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(this); + + Control control = viewer.getControl(); + Menu menu = menuMgr.createContextMenu(viewer.getTree ()); + control.setMenu (menu); + + // Make the Actions for the Context Menu + makeActions(); + + viewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + handleDoubleClick(event); + } + }); + + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + handleSelectionChanged(event); + } + }); + + viewer.getControl().addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + handleKeyPressed(e); + } + }); + + viewer.addTreeListener(expansionListener); + + getSite().registerContextMenu(menuMgr, viewer); + getSite().setSelectionProvider(viewer); + getSite().getPage().addPartListener(partListener); + + if (memento != null) + restoreState (memento); + memento = null; + + fillActionBars(); + + } + + /* (non-Javadoc) + * Method declared on IWorkbenchPart. + */ + public void dispose() { + getSite().getPage().removePartListener(partListener); + CPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); + if (viewer != null) { + viewer.removeTreeListener(expansionListener); + CPlugin.getDefault().getProblemMarkerManager().removeListener(viewer); + } + super.dispose(); + } + + /** + * An editor has been activated. Set the selection in this navigator + * to be the editor's input, if linking is enabled. + */ + void editorActivated(IEditorPart editor) { + if (!CPluginPreferencePage.isLinkToEditor()) { + return; + } + + IEditorInput input = editor.getEditorInput(); + if (input instanceof IFileEditorInput) { + CoreModel factory = CoreModel.getDefault(); + IFileEditorInput fileInput = (IFileEditorInput) input; + IFile file = fileInput.getFile(); + ICElement celement = factory.create(file); + if (celement != null) { + ISelection newSelection = new StructuredSelection(celement); + if (!viewer.getSelection().equals(newSelection)) { + viewer.setSelection(newSelection); + } + } + } + } + + CLibFilter getLibraryFilter () { + return clibFilter; + } + + /** + * Returns the pattern filter for this view. + * @return the pattern filter + */ + CPatternFilter getPatternFilter() { + return patternFilter; + } + + + TreeViewer getViewer () { + return viewer; + } + + /** + * Create self's action objects + */ + void makeActions() { + Shell shell = getViewSite().getShell(); + + openIncludeAction = new OpenIncludeAction (viewer); + openFileAction = new OpenFileAction(getSite().getPage()); + openSystemEditorAction = new OpenSystemEditorAction(getSite().getPage()); + refreshAction = new RefreshAction(shell); + //buildAction = new BuildAction(shell, IncrementalProjectBuilder.INCREMENTAL_BUILD); + //rebuildAction = new BuildAction(shell, IncrementalProjectBuilder.FULL_BUILD); + makeTargetAction = new MakeTargetAction(shell); + moveResourceAction = new MoveResourceAction (shell); + copyResourceAction = new CopyResourceAction(shell); + renameResourceAction = new RenameResourceAction(shell, viewer.getTree()); + deleteResourceAction = new DeleteResourceAction(shell); + + createFileAction = new CreateFileAction(shell); + // overwrite the default name + String fileLabel = CPlugin.getDefault().getResourceBundle().getString("CreateFileAction.text"); + createFileAction.setText(fileLabel); + + createFolderAction = new CreateFolderAction(shell); + // overwrite the default name + String folderLabel = CPlugin.getDefault().getResourceBundle().getString("CreateFolderAction.text"); + createFolderAction.setText(folderLabel); + + + newWizardAction = new NewWizardAction(); + closeResourceAction = new CloseResourceAction(shell); + + //sortByNameAction = new SortViewAction(this, false); + //sortByTypeAction = new SortViewAction(this, true); + + patternFilterAction = new FilterSelectionAction(shell, this, "Filters.."); + clibFilterAction = new ShowLibrariesAction(shell, this, "Show Referenced Libs"); + + goIntoAction = new GoIntoAction(frameList); + backAction = new BackAction(frameList); + forwardAction = new ForwardAction(frameList); + upAction = new UpAction(frameList); + + addBookmarkAction = new AddBookmarkAction(shell); + //propertyDialogAction = new PropertyDialogAction(shell, viewer); + propertyDialogAction = new PropertyDialogAction(shell, + new ISelectionProvider () { + public void addSelectionChangedListener(ISelectionChangedListener listener) { + viewer.addSelectionChangedListener (listener); + } + public ISelection getSelection() { + return convertSelection (viewer.getSelection ()); + } + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + viewer.removeSelectionChangedListener (listener); + } + public void setSelection(ISelection selection) { + viewer.setSelection (selection); + } + }); + + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(IWorkbenchActionConstants.DELETE, deleteResourceAction); + actionBars.setGlobalActionHandler(IWorkbenchActionConstants.BOOKMARK, addBookmarkAction); + + } + + /** + * Updates all actions with the given selection. + * Necessary when popping up a menu, because some of the enablement criteria + * may have changed, even if the selection in the viewer hasn't. + * E.g. A project was opened or closed. + */ + void updateActions(IStructuredSelection selection) { + //buildAction.selectionChanged(selection); + //rebuildAction.selectionChanged(selection); + makeTargetAction.selectionChanged(selection); + copyResourceAction.selectionChanged(selection); + refreshAction.selectionChanged(selection); + moveResourceAction.selectionChanged(selection); + openFileAction.selectionChanged(selection); + openSystemEditorAction.selectionChanged(selection); + propertyDialogAction.selectionChanged(selection); + renameResourceAction.selectionChanged(selection); + closeResourceAction.selectionChanged(selection); + //sortByTypeAction.selectionChanged(selection); + //sortByNameAction.selectionChanged(selection); + updateGlobalActions(selection); + } + + /** + * Updates the global actions with the given selection. + * Be sure to invoke after actions objects have updated, since can* methods delegate to action objects. + */ + void updateGlobalActions(IStructuredSelection selection) { + createFileAction.selectionChanged (selection); + createFolderAction.selectionChanged (selection); + deleteResourceAction.selectionChanged(selection); + addBookmarkAction.selectionChanged(selection); + + // Ensure Copy global action targets correct action, + // either copyProjectAction or copyResourceAction, + // depending on selection. + copyResourceAction.selectionChanged(selection); + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(IWorkbenchActionConstants.COPY, copyResourceAction); + actionBars.updateActionBars(); + renameResourceAction.selectionChanged(selection); + } + + + //---- Action handling ---------------------------------------------------------- + + IStructuredSelection convertSelection(ISelection s) { + List converted = new ArrayList(); + if (s instanceof StructuredSelection) { + Object[] elements= ((StructuredSelection)s).toArray(); + for (int i= 0; i < elements.length; i++) { + Object e = elements[i]; + if (e instanceof IAdaptable) { + IResource r = (IResource)((IAdaptable)e).getAdapter(IResource.class); + if (r != null) + converted.add(r); + } + } + } + return new StructuredSelection(converted.toArray()); + } + + IStructuredSelection convertSelectionToCElement(ISelection s) { + List converted = new ArrayList(); + if (s instanceof StructuredSelection) { + Object[] elements= ((StructuredSelection)s).toArray(); + for (int i= 0; i < elements.length; i++) { + Object e = elements[i]; + if (e instanceof IAdaptable) { + ICElement c = (ICElement)((IAdaptable)e).getAdapter(ICElement.class); + if (c != null) + converted.add(c); + } + } + } + return new StructuredSelection(converted.toArray()); + } + + /** + * Called when the context menu is about to open. + * Override to add your own context dependent menu contributions. + */ + public void menuAboutToShow(IMenuManager menu) { + IStructuredSelection selection= (IStructuredSelection) viewer.getSelection(); + if (selection.isEmpty()) { + new NewWizardMenu(menu, getSite().getWorkbenchWindow(), false); + menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));//$NON-NLS-1$ + return; + } + + updateActions (convertSelection(selection)); + //updateActions (selection); + addNewMenu(menu, selection); + menu.add(new Separator()); + addOpenMenu(menu, selection); + menu.add(new Separator()); + addBuildMenu(menu, selection); + menu.add(new Separator ()); + addRefreshMenu (menu, selection); + menu.add(new Separator()); + addIOMenu(menu, selection); + menu.add(new Separator()); + addBookMarkMenu (menu, selection); + //menu.add(new Separator()); + menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));//$NON-NLS-1$ + addPropertyMenu(menu, selection); + } + + void addNewMenu (IMenuManager menu, IStructuredSelection selection) { + + MenuManager newMenu = new MenuManager("New"); + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + + if (selection.size() == 1) { + if (resource != null && resource instanceof IContainer) { + newMenu.add (createFileAction); + newMenu.add (createFolderAction); + } + } + //new NewWizardMenu(newMenu, getSite().getWorkbenchWindow(), false); + newMenu.add(new Separator()); + newMenu.add(newWizardAction); + menu.add(newMenu); + + if (resource == null) + return; + + menu.add (new Separator ()); + if (selection.size() == 1 && resource instanceof IContainer) { + menu.add(goIntoAction); + } + + MenuManager gotoMenu = new MenuManager("GoTo"); + menu.add(gotoMenu); + if (viewer.isExpandable(element)) { + gotoMenu.add(backAction); + gotoMenu.add(forwardAction); + gotoMenu.add(upAction); + } + + } + + void addOpenMenu(IMenuManager menu, IStructuredSelection selection) { + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + if (resource == null) + return; + + // Create a menu flyout. + //MenuManager submenu= new MenuManager("Open With"); //$NON-NLS-1$ + //submenu.add(new OpenWithMenu(getSite().getPage(), (IFile) resource)); + //menu.add(submenu); + if (resource instanceof IFile) + menu.add(openFileAction); + + fillOpenWithMenu(menu, selection); + fillOpenToMenu(menu, selection); + } + + + void addBuildMenu(IMenuManager menu, IStructuredSelection selection) { + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + if (resource == null) + return; + + //if (resource instanceof IProject) { + // Allow manual incremental build only if auto build is off. + //if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) { + //menu.add(buildAction); + //} + //} + boolean isContainer = (resource instanceof IContainer); + if (isContainer) { + MakeTarget[] aBuild = new MakeTarget[1]; + aBuild[0] = new MakeTarget(resource, ""); + menu.add(new MakeAction(aBuild, getViewSite().getShell(), "Build")); + + MakeTarget[] aReBuild = new MakeTarget[1]; + aReBuild[0] = new MakeTarget(resource, "clean all"); + menu.add(new MakeAction(aReBuild, getViewSite().getShell(), "Rebuild")); + MakeTarget[] aClean = new MakeTarget[1]; + aClean[0] = new MakeTarget(resource, "clean"); + menu.add(new MakeAction(aClean, getViewSite().getShell(), "Clean")); + } + //if (resource instanceof IProject) { + // menu.add(rebuildAction); + //} + MenuManager submenu= new MenuManager("Make"); + if (isContainer) { + String [] directives = MakeUtil.getPersistentTargets(resource); + if (directives.length > 0) { + for (int i = 0; i < directives.length; i++) { + MakeTarget[] a = new MakeTarget[1]; + a[0] = new MakeTarget(resource, directives[i]); + submenu.add(new MakeAction(a, getViewSite().getShell(), directives[i])); + } + } + } + menu.add(submenu); + if (isContainer) { + menu.add(makeTargetAction); + } + } + + void addRefreshMenu (IMenuManager menu, IStructuredSelection selection) { + menu.add(refreshAction); + } + + void addIOMenu (IMenuManager menu, IStructuredSelection selection) { + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + if (resource == null) + return; + + menu.add(new Separator ()); + + if (resource instanceof IProject) { + menu.add(closeResourceAction); + } + + if (resource instanceof IFile || resource instanceof IFolder) { + menu.add(copyResourceAction); + menu.add(moveResourceAction); + } + + if (!(element instanceof IArchiveContainer || element instanceof IBinaryContainer)) { + menu.add(renameResourceAction); + menu.add(deleteResourceAction); + } + + } + + void addBookMarkMenu (IMenuManager menu, IStructuredSelection selection) { + //if (resource instanceof IFile) { + menu.add(addBookmarkAction); + //} + } + + void addPropertyMenu (IMenuManager menu, IStructuredSelection selection) { + propertyDialogAction.selectionChanged(convertSelection(selection)); + if (propertyDialogAction.isApplicableForSelection()) { + menu.add(propertyDialogAction); + } + } + + + /** + * Add "open with" actions to the context sensitive menu. + * @param menu the context sensitive menu + * @param selection the current selection in the project explorer + */ + void fillOpenWithMenu(IMenuManager menu, IStructuredSelection selection) { + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + if (resource == null) + return; + + // If one file is selected get it. + // Otherwise, do not show the "open with" menu. + if (selection.size() != 1) + return; + + if (!(resource instanceof IFile)) + return; + + // Create a menu flyout. + MenuManager submenu = new MenuManager("Open With"); //$NON-NLS-1$ + submenu.add(new OpenWithMenu(getSite().getPage(), (IFile) resource)); + + // Add the submenu. + menu.add(submenu); + } + + /** + * Add "open to" actions to the context sensitive menu. + * @param menu the context sensitive menu + * @param selection the current selection in the project explorer + */ + void fillOpenToMenu(IMenuManager menu, IStructuredSelection selection) + { + IAdaptable element = (IAdaptable)selection.getFirstElement(); + IResource resource = (IResource)element.getAdapter(IResource.class); + if (resource == null) + return; + + // If one file is selected get it. + // Otherwise, do not show the "open with" menu. + if (selection.size() != 1) + return; + + if (!(resource instanceof IContainer)) + return; + + // Create a menu flyout. + MenuManager submenu = new MenuManager("Open In Perspective"); //$NON-NLS-1$ + submenu.add(new OpenPerspectiveMenu(getSite().getWorkbenchWindow(), resource)); + menu.add(submenu); + + } + + + /** + * Returns the tool tip text for the given element. + */ + String getToolTipText(Object element) { + if (element instanceof IResource) { + IPath path = ((IResource) element).getFullPath(); + if (path.isRoot()) { + return "CVIEW"; //$NON-NLS-1$ + } else { + return path.makeRelative().toString(); + } + } else { + return ((ILabelProvider) viewer.getLabelProvider()).getText(element); + } + } + + /** + * Returns the message to show in the status line. + * + * @param selection the current selection + * @return the status line message + */ + String getStatusLineMessage(IStructuredSelection selection) { + if (selection.size() == 1) { + Object o = selection.getFirstElement(); + if (o instanceof IResource) { + return ((IResource) o).getFullPath().makeRelative().toString(); + } else if (o instanceof ICElement) { + ICElement celement = (ICElement)o; + IResource res = (IResource)celement.getAdapter(IResource.class); + if (res != null) { + if (celement.getElementType() == ICElement.C_CONTAINER) { + ICElement parent = celement.getParent(); + IResource proj = (IResource)parent.getAdapter(IResource.class); + if (celement instanceof IArchiveContainer) + return proj.getFullPath() + " - archives"; + else + return proj.getFullPath() + " - binaries"; + } else if (celement.getElementType() > ICElement.C_UNIT) { + return res.getFullPath().toString() + " - [" + celement.getElementName() +"]"; + } + return res.getFullPath().toString(); + } + return celement.getElementName(); + } else { + return "ItemSelected"; //$NON-NLS-1$ + } + } + if (selection.size() > 1) { + return "StatusLine"; + } + return "";//$NON-NLS-1$ + } + + void updateTitle () { + Object input= getViewer().getInput(); + String viewName= getConfigurationElement().getAttribute("name"); //$NON-NLS-1$ + if (input == null || (input instanceof ICRoot)) { + setTitle(viewName); + setTitleToolTip(""); //$NON-NLS-1$ + } else { + ILabelProvider labelProvider = (ILabelProvider) getViewer().getLabelProvider(); + String inputText= labelProvider.getText(input); + setTitle(inputText); + setTitleToolTip(getToolTipText(input)); + } + } + + /** + * Returns the tree viewer which shows the resource hierarchy. + */ + TreeViewer getResourceViewer() { + return viewer; + } + + /** + * Updates the message shown in the status line. + * + * @param selection the current selection + */ + void updateStatusLine(IStructuredSelection selection) { + String msg = getStatusLineMessage(selection); + getViewSite().getActionBars().getStatusLineManager().setMessage(msg); + } + + + void fillActionBars() { + IActionBars actionBars= getViewSite().getActionBars(); + IToolBarManager toolBar = actionBars.getToolBarManager(); + toolBar.add(backAction); + toolBar.add(forwardAction); + toolBar.add(upAction); + actionBars.updateActionBars(); + + IMenuManager menu = actionBars.getMenuManager(); + //menu.add (clibFilterAction); + menu.add (patternFilterAction); + } + + /** + * Sets the decorator for the package explorer. + * + * @param decorator a label decorator or null for no decorations. + */ + public void setLabelDecorator(ILabelDecorator decorator) { + ILabelProvider cProvider= new StandardCElementLabelProvider(); + if (decorator == null) { + viewer.setLabelProvider(cProvider); + } else { + viewer.setLabelProvider(new DecoratingLabelProvider(cProvider, decorator)); + } + } + + public void propertyChange(PropertyChangeEvent event) { + if (viewer == null) + return; + + boolean refreshViewer= false; + + if (event.getProperty() == CPluginPreferencePage.SHOW_CU_CHILDREN) { + boolean showCUChildren= CPluginPreferencePage.showCompilationUnitChildren(); + ((CContentProvider)viewer.getContentProvider()).setProvideMembers(showCUChildren); + refreshViewer= true; + } + + if (refreshViewer) + viewer.refresh(); + } + + /** + * Links to editor (if option enabled) + */ + void linkToEditor(IStructuredSelection selection) { + if (!CPluginPreferencePage.isLinkToEditor()) { + return; + } + + Object obj = selection.getFirstElement(); + if (obj instanceof IFile && selection.size() == 1) { + IFile file = (IFile) obj; + IWorkbenchPage page = getSite().getPage(); + IEditorPart editorArray[] = page.getEditors(); + for (int i = 0; i < editorArray.length; ++i) { + IEditorPart editor = editorArray[i]; + IEditorInput input = editor.getEditorInput(); + if (input instanceof IFileEditorInput + && file.equals(((IFileEditorInput)input).getFile())) { + page.bringToTop(editor); + return; + } + } + } else if (obj instanceof ICElement) { + ICElement celement = (ICElement) obj; + IResource res = (IResource)celement.getAdapter(IResource.class); + if (res == null || !(res instanceof IFile)) + return; + IWorkbenchPage page = getSite().getPage(); + IEditorPart editorArray[] = page.getEditors(); + for (int i = 0; i < editorArray.length; ++i) { + IEditorPart editor = editorArray[i]; + IEditorInput input = editor.getEditorInput(); + if (input instanceof IFileEditorInput + && res.equals(((IFileEditorInput)input).getFile())) { + page.bringToTop(editor); + if (editor instanceof CEditor) { + CEditor e = (CEditor)editor; + e.selectionChanged (new SelectionChangedEvent (e.getOutlinePage (), selection)); + } + return; + } + } + + } + } + + void restoreFilters() { + // restore pattern filters + IMemento filtersMem = memento.getChild(TAG_FILTERS); + if (filtersMem != null) { + IMemento children[]= filtersMem.getChildren(TAG_FILTER); + String filters[]= new String[children.length]; + for (int i = 0; i < children.length; i++) { + filters[i]= children[i].getString(TAG_ELEMENT); + } + getPatternFilter().setPatterns(filters); + } else { + getPatternFilter().setPatterns(new String[0]); + } + + //restore library + String show = memento.getString(TAG_SHOWLIBRARIES); + if (show != null) { + getLibraryFilter().setShowLibraries(show.equals("true")); //$NON-NLS-1$ + } + else + initFilterFromPreferences(); + } + + void restoreState(IMemento memento) { + //ICelement container = CElementFactory.getDefault().getRoot(); + CoreModel factory = CoreModel.getDefault(); + IMemento childMem = memento.getChild(TAG_EXPANDED); + if(childMem != null) { + ArrayList elements = new ArrayList(); + IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT); + for (int i = 0; i < elementMem.length; i++){ + String p = elementMem[i].getString(TAG_PATH); + if (p != null) { + IPath path = new Path(p); + ICElement element = factory.create(path); + if (element != null) + elements.add(element); + } + } + viewer.setExpandedElements(elements.toArray()); + } + childMem = memento.getChild(TAG_SELECTION); + if(childMem != null) { + ArrayList list = new ArrayList(); + IMemento[] elementMem = childMem.getChildren(TAG_ELEMENT); + for (int i = 0; i < elementMem.length; i++){ + String p = elementMem[i].getString(TAG_PATH); + if (p != null) { + IPath path = new Path(p); + ICElement element = factory.create(path); + if (element != null) + list.add(element); + } + } + viewer.setSelection(new StructuredSelection(list)); + } + + Tree tree = viewer.getTree(); + //save vertical position + ScrollBar bar = tree.getVerticalBar(); + if (bar != null) { + try { + String posStr = memento.getString(TAG_VERTICAL_POSITION); + int position; + position = new Integer(posStr).intValue(); + bar.setSelection(position); + position = new Integer(posStr).intValue(); + bar.setSelection(position); + } catch (NumberFormatException e){} + } + bar = tree.getHorizontalBar(); + if (bar != null) { + try { + String posStr = memento.getString(TAG_HORIZONTAL_POSITION); + int position; + position = new Integer(posStr).intValue(); + bar.setSelection(position); + } catch (NumberFormatException e){} + } + } + + public void saveState(IMemento memento) { + if(viewer == null) { + if(this.memento != null) //Keep the old state; + memento.putMemento(this.memento); + return; + } + + //save expanded elements + Tree tree = viewer.getTree(); + Object expandedElements[] = viewer.getExpandedElements(); + if (expandedElements.length > 0) { + IMemento expandedMem = memento.createChild(TAG_EXPANDED); + for (int i = 0; i < expandedElements.length; i++) { + Object o = expandedElements[i]; + // Do not save expanded binary files are libraries. + if (o instanceof IParent + && ! (o instanceof IArchiveContainer || o instanceof IBinaryContainer + || o instanceof IBinary || o instanceof IArchive)) { + IMemento elementMem = expandedMem.createChild(TAG_ELEMENT); + ICElement e = (ICElement)o; + IResource res = (IResource)e.getAdapter(IResource.class); + if (res != null) + elementMem.putString(TAG_PATH, res.getLocation().toOSString()); + } + } + } + + //save selection + Object elements[] = ((IStructuredSelection)viewer.getSelection()).toArray(); + if(elements.length > 0) { + IMemento selectionMem = memento.createChild(TAG_SELECTION); + for (int i = 0; i < elements.length; i++) { + ICElement e = (ICElement)elements[i]; + IResource r = (IResource)e.getAdapter(IResource.class); + if (r != null) { + IMemento elementMem = selectionMem.createChild(TAG_ELEMENT); + elementMem.putString(TAG_PATH,r.getLocation().toString()); + } + } + } + + //save vertical position + ScrollBar bar = tree.getVerticalBar(); + int position = bar != null ? bar.getSelection():0; + memento.putString(TAG_VERTICAL_POSITION,String.valueOf(position)); + //save horizontal position + bar = tree.getHorizontalBar(); + position = bar != null ? bar.getSelection():0; + memento.putString(TAG_HORIZONTAL_POSITION,String.valueOf(position)); + + //save filters + String filters[] = getPatternFilter().getPatterns(); + if(filters.length > 0) { + IMemento filtersMem = memento.createChild(TAG_FILTERS); + for (int i = 0; i < filters.length; i++){ + IMemento child = filtersMem.createChild(TAG_FILTER); + child.putString(TAG_ELEMENT,filters[i]); + } + } + //save library filter + boolean showLibraries= getLibraryFilter().getShowLibraries(); + String show= "true"; //$NON-NLS-1$ + if (!showLibraries) + show= "false"; //$NON-NLS-1$ + memento.putString(TAG_SHOWLIBRARIES, show); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java new file mode 100644 index 00000000000..57df989b4bd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDragAdapter.java @@ -0,0 +1,152 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSource; +import org.eclipse.swt.dnd.DragSourceAdapter; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.part.ResourceTransfer; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ICFolder; + +/** + * Implements drag behaviour when items are dragged out of the + * resource navigator. + */ +class CViewDragAdapter extends DragSourceAdapter { + ISelectionProvider selectionProvider; + + /** + * Invoked when an action occurs. + * Argument context is the Window which contains the UI from which this action was fired. + * This default implementation prints the name of this class and its label. + * @see IAction#run + */ + public void dragFinished(DragSourceEvent event) { + if (event.doit && event.detail == DND.DROP_MOVE) { + //delete the old elements + final int typeMask = IResource.FOLDER | IResource.FILE; + IResource[] resources = getSelectedResources(typeMask); + if (resources == null) + return; + for (int i = 0; i < resources.length; i++) { + try { + resources[i].delete(true, null); + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + } + + /** + * Returns the data to be transferred in a drag and drop + * operation. + */ + public void dragSetData(DragSourceEvent event) { + final int typeMask = IResource.FILE | IResource.FOLDER; + IResource[] resources = getSelectedResources(typeMask); + if (resources == null || resources.length == 0) + return; + + //use resource transfer if possible + if (ResourceTransfer.getInstance().isSupportedType(event.dataType)) { + event.data = resources; + return; + } + + //resort to a file transfer + if (!FileTransfer.getInstance().isSupportedType(event.dataType)) + return; + + // Get the path of each file and set as the drag data + final int len = resources.length; + String[] fileNames = new String[len]; + for (int i = 0, length = len; i < length; i++) { + fileNames[i] = resources[i].getLocation().toOSString(); + } + event.data = fileNames; + } + + /** + * All selection must be files or folders. + */ + public void dragStart(DragSourceEvent event) { + + // Workaround for 1GEUS9V + DragSource dragSource = (DragSource)event.widget; + Control control = dragSource.getControl(); + if (control != control.getDisplay().getFocusControl()){ + event.doit = false; + return; + } + + IStructuredSelection selection = (IStructuredSelection)selectionProvider.getSelection(); + for (Iterator i = selection.iterator(); i.hasNext();) { + Object next = i.next(); + if (!(next instanceof ICFile || next instanceof ICFolder)) { + event.doit = false; + return; + } + } + event.doit = true; + } + + protected IResource[] getSelectedResources(int resourceTypes) { + List resources = new ArrayList(); + IResource[] result = new IResource[0]; + + ISelection selection = selectionProvider.getSelection(); + if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) { + return null; + } + IStructuredSelection structuredSelection = (IStructuredSelection)selection; + if (structuredSelection == null) + return null; + + // loop through list and look for matching items + Iterator enum = structuredSelection.iterator(); + while (enum.hasNext()) { + Object obj = enum.next(); + if (obj instanceof ICElement) { + try { + IResource res = ((ICElement)obj).getUnderlyingResource(); + if (res != null) { + if ((res.getType() & resourceTypes) == res.getType()) { + resources.add(res); + } + } + } catch (CModelException e) { + } + } + } + result = new IResource[resources.size()]; + resources.toArray(result); + return result; + } + + /** + * CViewDragAction constructor comment. + */ + public CViewDragAdapter(ISelectionProvider provider) { + selectionProvider = provider; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java new file mode 100644 index 00000000000..3532a484ad2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewDropAdapter.java @@ -0,0 +1,467 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.CopyResourceAction; +import org.eclipse.ui.dialogs.IOverwriteQuery; +import org.eclipse.ui.part.PluginDropAdapter; +import org.eclipse.ui.part.ResourceTransfer; +import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; +import org.eclipse.ui.wizards.datatransfer.ImportOperation; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement;; + +/** + * Implements drop behaviour for drag and drop operations + * that land on the resource navigator. + */ +class CViewDropAdapter extends PluginDropAdapter implements IOverwriteQuery { + /** + * The time the mouse first started hovering over the current target + */ + protected long hoverStart = 0; + /** + * The amount of time to hover over a tree item before expanding it + */ + protected static final long hoverThreshold = 1500; + + /** + * A flag indicating that the drop has been cancelled by the user. + */ + protected boolean isCanceled = false; + /** + * A flag indicating that overwrites should always occur. + */ + protected boolean alwaysOverwrite = false; + + /** + * Copies or moves the source file to the given + * destination. If overwrite is true, any resource that + * already exists at the destination will be deleted before the + * copy/move occurs. + */ + protected IStatus doCopy(final IResource source, final IPath destination, final boolean overwrite) { + final boolean copy = getCurrentOperation() == DND.DROP_COPY; + final IStatus[] result = new IStatus[] { ok()}; + try { + new ProgressMonitorDialog(getShell()).run(true, true, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + try { + if (overwrite) { + //delete the destination + IResource oldResource = source.getWorkspace().getRoot().findMember(destination); + if (oldResource.exists()) { + oldResource.delete(true, null); + } + } + if (copy) { + IPath newName = destination; + if (source.getWorkspace().getRoot().exists(destination)) + newName = CopyResourceAction.getNewNameFor(destination, source.getWorkspace()); + if (newName != null) { + source.copy(newName, false, monitor); + } + } else { + source.move(destination, false, monitor); + } + } catch (CoreException e) { + result[0] = e.getStatus(); + } + } + }); + } catch (InvocationTargetException e) { + //implementation doesn't throw this + } catch (InterruptedException e) { + } + return result[0]; + } + + /** + * Copies the source into the target container. Returns a status object + * indicating success or failure. + */ + protected IStatus dragAndDropCopy(IContainer target, IResource source) { + if (isCanceled) { + return ok(); + } + if (getCurrentOperation() != DND.DROP_COPY && (source.equals(target) || source.getParent().equals(target))) { + return info("Same Source And Destination"); //$NON-NLS-1$ + } + if (source.getFullPath().isPrefixOf(target.getFullPath())) { + return error(source, "destination A SubFolder"); //$NON-NLS-1$ + } + IPath destination = target.getFullPath().append(source.getName()); + + IStatus result = doCopy(source, destination, false); + if (result.getCode() == IResourceStatus.PATH_OCCUPIED) { + if (alwaysOverwrite) { + return doCopy(source, destination, true); + } + String query = queryOverwrite(destination.toString()); + if (query == YES) { + return doCopy(source, destination, true); + } + if (query == CANCEL) { + isCanceled = true; + return ok(); + } + if (query == ALL) { + alwaysOverwrite = true; + return doCopy(source, destination, true); + } + if (query == NO) { + return ok(); + } + } + return result; + } + + /** + * Performs an import of the given file into the provided + * container. Returns a status indicating if the import was successful. + */ + protected IStatus dragAndDropImport(IContainer target, String filePath) { + File toImport = new File(filePath); + if (target.getLocation().equals(toImport)) { + return info(("DropAdapter.canNotDropOntoSelf")); //$NON-NLS-1$ + } + ImportOperation op = + new ImportOperation(target.getFullPath(), new File(toImport.getParent()), FileSystemStructureProvider.INSTANCE, this, Arrays.asList(new File[] {toImport})); + op.setCreateContainerStructure(false); + try { + new ProgressMonitorDialog(getShell()).run(true, true, op); + } catch (InterruptedException e) { + return info("Cancelled"); //$NON-NLS-1$ + } catch (InvocationTargetException e) { + return error("Drop Operation Error", e.getTargetException()); //$NON-NLS-1$ + } + return op.getStatus(); + } + + /** + * The mouse has moved over the drop target. If the + * target item has changed, notify the action and check + * that it is still enabled. + */ + public void dragOver(DropTargetEvent event) { + try { + //this method implements the UI behaviour that when the user hovers + //over an unexpanded tree item long enough, it will auto-expand. + Object oldTarget = getCurrentTarget(); + super.dragOver(event); + if (oldTarget != getCurrentTarget()) { + hoverStart = System.currentTimeMillis(); + } else { + //if we've been hovering over this item awhile, expand it. + if (hoverStart > 0 && (System.currentTimeMillis() - hoverStart) > hoverThreshold) { + expandSelection((TreeItem) event.item); + hoverStart = 0; + } + } + } catch (Throwable t) { + handleException(t, event); + } + } + + /** + * Returns an error status with the given info. + */ + protected IStatus error(String message, Throwable exception) { + return new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, exception); + } + + /** + * Returns an error status with the given info. + */ + protected IStatus error(String message) { + return error(message, null); + } + + /** + * Returns an error status, indicating why the given source + * could not be copied or moved. + */ + protected IStatus error(IResource source, String message) { + if (getCurrentOperation() == DND.DROP_COPY) { + return error("Can Not Copy", null); //$NON-NLS-1$ + } else { + return error("Can Not Move", null); //$NON-NLS-1$ + } + } + + /** + * Expands the selection of the given tree viewer. + */ + protected void expandSelection(TreeItem selection) { + if (selection == null) + return; + if (!selection.getExpanded()) { + TreeViewer treeViewer = (TreeViewer) getViewer(); + treeViewer.expandToLevel(selection.getData(), 1); + } + } + + /** + * Returns the actual target of the drop, given the resource + * under the mouse. If the mouse target is a file, then the drop actually + * occurs in its parent. If the drop location is before or after the + * mouse target, the target is also the parent. + */ + protected IContainer getActualTarget(IResource mouseTarget) { + /* if cursor is before or after mouseTarget, set target to parent */ + if (getCurrentLocation() == LOCATION_BEFORE || getCurrentLocation() == LOCATION_AFTER) { + return mouseTarget.getParent(); + } + /* if cursor is on a file, return the parent */ + if (mouseTarget.getType() == IResource.FILE) { + return mouseTarget.getParent(); + } + /* otherwise the mouseTarget is the real target */ + return (IContainer)mouseTarget; + } + + /** + * Returns the display + */ + protected Display getDisplay() { + return getViewer().getControl().getDisplay(); + } + + /** + * Returns the shell + */ + protected Shell getShell() { + return getViewer().getControl().getShell(); + } + + /** + * Returns an error status with the given info. + */ + protected IStatus info(String message) { + return new Status(IStatus.INFO, PlatformUI.PLUGIN_ID, 0, message, null); + } + + /** + * CViewDropAction constructor comment. + */ + public CViewDropAdapter(StructuredViewer viewer) { + super(viewer); + } + + /** + * Adds the given status to the list of problems. Discards + * OK statuses. If the status is a multi-status, only its children + * are added. + */ + protected void mergeStatus(MultiStatus status, IStatus toMerge) { + if (!toMerge.isOK()) { + status.merge(toMerge); + } + } + + /** + * Creates a status object from the given list of problems. + */ + protected IStatus multiStatus(List problems, String message) { + IStatus[] children = new IStatus[problems.size()]; + problems.toArray(children); + if (children.length == 1) { + return children[0]; + } else { + return new MultiStatus(PlatformUI.PLUGIN_ID, 0, children, message, null); + } + } + + /** + * Returns an status indicating success. + */ + protected IStatus ok() { + return new Status(Status.OK, PlatformUI.PLUGIN_ID, 0, "Ok", null); //$NON-NLS-1$ + } + + /** + * Opens an error dialog if necessary. Takes care of + * complex rules necessary for making the error dialog look nice. + */ + protected void openError(IStatus status) { + String genericTitle = "Error"; //$NON-NLS-1$ + int codes = IStatus.ERROR | IStatus.WARNING; + + //simple case: one error, not a multistatus + if (!status.isMultiStatus()) { + ErrorDialog.openError(getShell(), genericTitle, null, status, codes); + return; + } + + //one error, single child of multistatus + IStatus[] children = status.getChildren(); + if (children.length == 1) { + ErrorDialog.openError(getShell(), status.getMessage(), null, children[0], codes); + return; + } + //several problems + ErrorDialog.openError(getShell(), genericTitle, null, status, codes); + } + + /** + * Invoked when an action occurs. + * Argument context is the Window which contains the UI from which this action was fired. + * This default implementation prints the name of this class and its label. + * @see IAction#run + */ + public boolean performDrop(Object data) { + isCanceled = false; + alwaysOverwrite = false; + if (getCurrentTarget() == null || data == null) { + return false; + } + TransferData currentTransfer = getCurrentTransfer(); + if (ResourceTransfer.getInstance().isSupportedType(currentTransfer)) { + return performResourceDrop(data); + } + if (FileTransfer.getInstance().isSupportedType(currentTransfer)) { + return performFileDrop(data); + } + return super.performDrop(data); + } + + /** + * Performs a drop using the FileTransfer transfer type. + */ + protected boolean performFileDrop(Object data) { + MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 0, "Problem Importing", null); //$NON-NLS-1$ + mergeStatus(problems, validateTarget(getCurrentTarget())); + + Object obj = getCurrentTarget(); + IResource res = null; + if (obj instanceof ICElement) { + try { + res = ((ICElement)obj).getUnderlyingResource(); + } catch (CModelException e) { + } + } + IContainer targetResource = getActualTarget(res); + String[] names = (String[]) data; + for (int i = 0; i < names.length; i++) { + mergeStatus(problems, dragAndDropImport(targetResource, names[i])); + } + openError(problems); + return problems.isOK(); + } + + /** + * Performs a drop using the ResourceTransfer transfer type. + */ + protected boolean performResourceDrop(Object data) { + MultiStatus problems = new MultiStatus(PlatformUI.PLUGIN_ID, 1, "Problems Moving", null); //$NON-NLS-1$ + mergeStatus(problems, validateTarget(getCurrentTarget())); + + Object obj = getCurrentTarget(); + IResource res = null; + if (obj instanceof ICElement) { + try { + res = ((ICElement)obj).getUnderlyingResource(); + } catch (CModelException e) { + } + } + IContainer targetResource = getActualTarget(res); + IResource[] sources = (IResource[]) data; + for (int i = 0; i < sources.length; i++) { + mergeStatus(problems, dragAndDropCopy(targetResource, sources[i])); + } + openError(problems); + + //always return false because we don't want the source to clean up + return false; + } + + /* (non-Javadoc) + * Method declared on IOverWriteQuery + */ + public String queryOverwrite(String pathString) { + final String returnCode[] = {CANCEL}; + final String msg = "overwrite Query"; //$NON-NLS-1$ + final String[] options = {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL}; + getDisplay().syncExec(new Runnable() { + public void run() { + MessageDialog dialog = new MessageDialog(getShell(), "Question", null, msg, MessageDialog.QUESTION, options, 0); //$NON-NLS-1$ + dialog.open(); + int returnVal = dialog.getReturnCode(); + String[] returnCodes = {YES, NO, ALL, CANCEL}; + returnCode[0] = returnVal < 0 ? CANCEL : returnCodes[returnVal]; + } + }); + return returnCode[0]; + } + + /** + * This method is used to notify the action that some aspect of + * the drop operation has changed. + */ + public boolean validateDrop(Object target, int operation, TransferData transferType) { + if (super.validateDrop(target, operation, transferType)) { + return true; + } + return validateTarget(target).isOK(); + } + + /** + * Ensures that the drop target meets certain criteria + */ + protected IStatus validateTarget(Object target) { + if (target instanceof ICElement) { + try { + IResource r = ((ICElement)target).getUnderlyingResource(); + if (r == null) + return info("Target Must Be Resource"); //$NON-NLS-1$ + target = r; + } catch (CModelException e) { + } + } + if (!(target instanceof IResource)) { + return info("Target Must Be Resource"); //$NON-NLS-1$ + } + IResource resource = (IResource)target; + if (!resource.isAccessible()) { + return error("Can Not Drop Into Closed Project"); //$NON-NLS-1$ + } + IContainer destination = getActualTarget(resource); + if (destination.getType() == IResource.ROOT) { + return error("Resources Can Not Be Siblings"); //$NON-NLS-2$ + } + return ok(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewFrameSource.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewFrameSource.java new file mode 100644 index 00000000000..9502681bae5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewFrameSource.java @@ -0,0 +1,31 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.ui.views.framelist.TreeFrame; +import org.eclipse.ui.views.framelist.TreeViewerFrameSource; + +public class CViewFrameSource extends TreeViewerFrameSource { + private CView cview; + + protected TreeFrame createFrame(Object input) { + TreeFrame frame = super.createFrame(input); + frame.setToolTipText(cview.getToolTipText(input)); + return frame; + } + /** + * Also updates the title of the packages explorer + */ + protected void frameChanged(TreeFrame frame) { + super.frameChanged(frame); + cview.updateTitle(); + } + public CViewFrameSource(CView cview) { + super(cview.getResourceViewer()); + this.cview = cview; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewSorter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewSorter.java new file mode 100644 index 00000000000..6edcfb21c60 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/CViewSorter.java @@ -0,0 +1,78 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.viewers.ViewerSorter; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ICFolder; +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.IBinaryContainer; +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.ICFile; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CModelException; + +/** + * A sorter to sort the file and the folders in the C viewer in the following order: + * 1st Project + * 2nd BinaryContainer + * 3nd ArchiveContainer + * 4 Folder + * 5 C File + * 6 the reset + */ +public class CViewSorter extends ViewerSorter { + + public int category (Object element) { + if (element instanceof ICRoot) { + return 0; + } else if (element instanceof ICProject) { + return 10; + } else if (element instanceof IBinaryContainer) { + return 20; + } else if (element instanceof IArchiveContainer) { + return 30; + } else if (element instanceof ICFolder) { + return 40; + } else if (element instanceof ICFile) { + IResource res = null; + try { + res = ((ICFile)element).getUnderlyingResource(); + } catch (CModelException e) { + } + if (res != null) { + String ext = res.getFileExtension(); + if (ext != null) { + if (ext.equals("h") || ext.equals("hh")) { + return 50; + } + if (ext.equals("c") || ext.equals("C") || ext.equals("cc") || ext.equals("cpp")) { + return 51; + } + return 52; + } + return 53; + } + return 54; + } else if (element instanceof ICElement) { + String name = ((ICElement)element).getElementName(); + if (name.startsWith("__")) { + return 68; + } + if (name.charAt(0) == '_') { + return 67; + } + return 60; + } else if (element instanceof IArchive) { + return 70; + } + return 80; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DefaultAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DefaultAction.java new file mode 100644 index 00000000000..ff7099d249e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DefaultAction.java @@ -0,0 +1,28 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.jface.action.Action; +import org.eclipse.swt.SWT; + +public class DefaultAction extends Action { + + Shell shell; + + DefaultAction (Shell shell, String s) { + super (s); + this.shell = shell; + } + + public void run() { + MessageBox errorMsg = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + errorMsg.setText("WIP"); + errorMsg.setMessage ("Work In Progress"); + errorMsg.open(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FilterSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FilterSelectionAction.java new file mode 100644 index 00000000000..ed1e12dc45d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FilterSelectionAction.java @@ -0,0 +1,88 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.StringWriter; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.actions.SelectionProviderAction; +import org.eclipse.ui.dialogs.ListSelectionDialog; + +import org.eclipse.cdt.internal.ui.CPlugin; +//import org.eclipse.cdt.core.model.CElementFilters; + +/** + * The FilterAction is the class that adds the filter views to a PackagesView. + */ +class FilterSelectionAction extends SelectionProviderAction { + + + private CView cview; + private Shell shell; + + /** + * Create a new filter action + * @param shell the shell that will be used for the list selection + * @param packages the PackagesExplorerPart + * @param label the label for the action + */ + public FilterSelectionAction(Shell shell, CView cview, String label) { + super(cview.getViewer(), label); + setToolTipText("Filter Selection Action"); + setEnabled(true); + this.shell= shell; + this.cview= cview; + } + + /** + * Implementation of method defined on IAction. + */ + public void run() { + CPatternFilter filter= cview.getPatternFilter(); + FiltersContentProvider contentProvider= new FiltersContentProvider(filter); + + ListSelectionDialog dialog = + new ListSelectionDialog( + shell, + cview.getViewer(), + contentProvider, + new LabelProvider(), + "Select Filter"); //$NON-NLS-1$ + + dialog.setInitialSelections(contentProvider.getInitialSelections()); + dialog.open(); + if (dialog.getReturnCode() == dialog.OK) { + Object[] results= dialog.getResult(); + String[] selectedPatterns= new String[results.length]; + System.arraycopy(results, 0, selectedPatterns, 0, results.length); + filter.setPatterns(selectedPatterns); + CElementFilters.setPatterns(selectedPatterns); + saveInPreferences(selectedPatterns); + TreeViewer viewer= cview.getViewer(); + viewer.getControl().setRedraw(false); + viewer.refresh(); + viewer.getControl().setRedraw(true); + } + } + /** + * Save the supplied patterns in the preferences for the UIPlugin. + * They are saved in the format patern,pattern,. + */ + private void saveInPreferences(String[] patterns) { + CPlugin plugin= CPlugin.getDefault(); + StringWriter writer= new StringWriter(); + + for (int i = 0; i < patterns.length; i++) { + writer.write(patterns[i]); + writer.write(CPatternFilter.COMMA_SEPARATOR); + } + + plugin.getPreferenceStore().setValue( + CPatternFilter.FILTERS_TAG, writer.toString()); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FiltersContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FiltersContentProvider.java new file mode 100644 index 00000000000..f1f77ceede7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/FiltersContentProvider.java @@ -0,0 +1,104 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +import org.eclipse.cdt.internal.ui.CPlugin; + +/** + * The FiltersContentProvider provides the elements for use by the list dialog + * for selecting the patterns to apply. + */ +class FiltersContentProvider implements IStructuredContentProvider { + private static List fgDefinedFilters; + private static List fgDefaultFilters; + + private CPatternFilter filter; + + /** + * Disposes of this content provider. + * This is called by the viewer when it is disposed. + */ + public void dispose() {} + /** + * Returns the filters which are enabled by default. + * + * @return a list of strings + */ + public static List getDefaultFilters() { + if (fgDefaultFilters == null) { + readFilters(); + } + return fgDefaultFilters; + } + /** + * Returns the filters currently defined for the workbench. + */ + public static List getDefinedFilters() { + if (fgDefinedFilters == null) { + readFilters(); + } + return fgDefinedFilters; + } + /* (non-Jaadoc) + * Method declared in IStructuredContentProvider. + */ + public Object[] getElements(Object inputElement) { + return getDefinedFilters().toArray(); + } + /** + * Return the initially selected values + * @return java.lang.String[] + */ + public String[] getInitialSelections() { + return filter.getPatterns(); + } + /* (non-Javadoc) + * Method declared on IContentProvider. + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + /** + * Create a FiltersContentProvider using the selections from the suppliec + * resource filter. + */ + public FiltersContentProvider(CPatternFilter filter) { + this.filter= filter; + } + /** + * Reads the filters currently defined for the workbench. + */ + private static void readFilters() { + fgDefinedFilters = new ArrayList(); + fgDefaultFilters = new ArrayList(); + CPlugin plugin = CPlugin.getDefault(); + if (plugin != null) { + IExtensionPoint extension = plugin.getDescriptor().getExtensionPoint(CPatternFilter.FILTERS_TAG); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for(int i = 0; i < extensions.length; i++){ + IConfigurationElement [] configElements = extensions[i].getConfigurationElements(); + for(int j = 0; j < configElements.length; j++){ + String pattern = configElements[j].getAttribute("pattern"); //$NON-NLS-1$ + if (pattern != null) + fgDefinedFilters.add(pattern); + String selected = configElements[j].getAttribute("selected"); //$NON-NLS-1$ + if (selected != null && selected.equalsIgnoreCase("true")) //$NON-NLS-1$ + fgDefaultFilters.add(pattern); + } + } + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/ShowLibrariesAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/ShowLibrariesAction.java new file mode 100644 index 00000000000..725bce6f73f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/ShowLibrariesAction.java @@ -0,0 +1,69 @@ +package org.eclipse.cdt.internal.ui.cview; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.actions.SelectionProviderAction; + +import org.eclipse.cdt.internal.ui.CPlugin; + +/** + * The ShowLibrariesAction is the class that adds the filter views to a PackagesView. + */ +class ShowLibrariesAction extends SelectionProviderAction { + + private CView cview; + private Shell shell; + + /** + * Create a new filter action + * @param shell the shell that will be used for the list selection + * @param packages the PackagesExplorerPart + * @param label the label for the action + */ + public ShowLibrariesAction(Shell shell, CView cview, String label) { + super(cview.getViewer(), label); + this.cview = cview; + CLibFilter filter = cview.getLibraryFilter(); + setChecked(filter.getShowLibraries()); + updateToolTipText(); + setEnabled(true); + this.shell= shell; + } + + /** + * Implementation of method defined on IAction. + */ + public void run() { + CLibFilter filter = cview.getLibraryFilter(); + filter.setShowLibraries(isChecked()); + updateToolTipText(); + saveInPreferences(); + + cview.getViewer().getControl().setRedraw(false); + cview.getViewer().refresh(); + cview.getViewer().getControl().setRedraw(true); + } + + /** + * Save the supplied patterns in the preferences for the UIPlugin. + * They are saved in the format patern,pattern,. + */ + private void saveInPreferences() { + CPlugin plugin = CPlugin.getDefault(); + Boolean b = new Boolean (cview.getLibraryFilter().getShowLibraries()); + + plugin.getPreferenceStore().putValue(cview.TAG_SHOWLIBRARIES, b.toString()); + } + + private void updateToolTipText() { + CLibFilter filter = cview.getLibraryFilter(); + if (filter.getShowLibraries()) + setToolTipText("Hide Referenced Libs"); + else + setToolTipText("Show Referenced Libs"); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java new file mode 100644 index 00000000000..be718ca673e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/AbstractElementListSelectionDialog.java @@ -0,0 +1,277 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.viewers.ILabelProvider; + +/** + * A class to select one or more elements out of an indexed property + */ +public abstract class AbstractElementListSelectionDialog extends SelectionStatusDialog { + + private ILabelProvider fRenderer; + private boolean fIgnoreCase; + private boolean fIsMultipleSelection; + + private SelectionList fSelectionList; + private Label fMessage; + private ISelectionValidator fValidator; + + private String fMessageText; + private String fEmptyListMessage; + private String fNothingSelectedMessage; + + private StatusInfo fCurrStatus; + + /* + * @private + */ + private void access$superOpen() { + super.open(); + } + /* + * @private + * @see Dialog#cancelPressed + */ + protected void cancelPressed() { + setResult(null); + super.cancelPressed(); + } + protected Point computeInitialSize() { + return new Point(convertWidthInCharsToPixels(60), convertHeightInCharsToPixels(18)); + } + /* + * @private + * @see Window#createDialogArea(Composite) + */ + protected Control createDialogArea(Composite parent) { + Composite contents= (Composite)super.createDialogArea(parent); + + fMessage= createMessage(contents); + + int flags= fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE; + fSelectionList= new SelectionList(contents, flags | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, + fRenderer, fIgnoreCase); + + fSelectionList.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + handleDoubleClick(); + } + public void widgetSelected(SelectionEvent e) { + verifyCurrentSelection(); + } + }); + + GridData spec= new GridData(); + Point initialSize= computeInitialSize(); + spec.widthHint= initialSize.x; + spec.heightHint= initialSize.y; + spec.grabExcessVerticalSpace= true; + spec.grabExcessHorizontalSpace= true; + spec.horizontalAlignment= spec.FILL; + spec.verticalAlignment= spec.FILL; + fSelectionList.setLayoutData(spec); + + return contents; + } + /** + * Creates the message text widget and sets layout data. + */ + protected Label createMessage(Composite parent) { + Label text= new Label(parent, SWT.NULL); + text.setText(fMessageText); + GridData spec= new GridData(); + spec.grabExcessVerticalSpace= false; + spec.grabExcessHorizontalSpace= true; + spec.horizontalAlignment= spec.FILL; + spec.verticalAlignment= spec.BEGINNING; + text.setLayoutData(spec); + return text; + } + /* + * @private + * @see Window#create(Shell) + */ + public void create() { + super.create(); + if (isEmptyList()) { + fMessage.setEnabled(false); + fSelectionList.setEnabled(false); + } else { + verifyCurrentSelection(); + fSelectionList.selectFilterText(); + fSelectionList.setFocus(); + } + } + /** + * Returns the currently used filter text. + */ + protected String getFilter() { + return fSelectionList.getFilter(); + } + /** + * Returns the selection indices. + */ + protected int[] getSelectionIndices() { + return fSelectionList.getSelectionIndices(); + } + /** + * Returns the widget selection. Returns empty list when the widget is not + * usable. + */ + protected List getWidgetSelection() { + if (fSelectionList == null || fSelectionList.isDisposed()) + return new ArrayList(0); + return fSelectionList.getSelection(); + } + /** + * An element as been selected in the list by double clicking on it. + * Emulate a OK button pressed to close the dialog. + */ + protected abstract void handleDoubleClick(); + /** + * Checks whether the list of elements is empty or not. + */ + protected boolean isEmptyList() { + if (fSelectionList == null) + return true; + return fSelectionList.isEmptyList(); + } + /** + * Constructs a list selection dialog. + * @param renderer The label renderer used + * @param ignoreCase Decides if the match string ignores lower/upppr case + * @param multipleSelection Allow multiple selection + */ + protected AbstractElementListSelectionDialog(Shell parent, String title, Image image, ILabelProvider renderer, boolean ignoreCase, boolean multipleSelection) { + super(parent); + setTitle(title); + setImage(image); + fRenderer= renderer; + fIgnoreCase= ignoreCase; + fIsMultipleSelection= multipleSelection; + + fMessageText= ""; //$NON-NLS-1$ + + fCurrStatus= new StatusInfo(); + + fValidator= null; + fEmptyListMessage= ""; //$NON-NLS-1$ + fNothingSelectedMessage= ""; //$NON-NLS-1$ + } + /** + * Constructs a list selection dialog. + * @param renderer The label renderer used + * @param ignoreCase Decides if the match string ignores lower/upppr case + * @param multipleSelection Allow multiple selection + */ + protected AbstractElementListSelectionDialog(Shell parent, ILabelProvider renderer, boolean ignoreCase, boolean multipleSelection) { + this(parent, "", null, renderer, ignoreCase, multipleSelection); //$NON-NLS-1$ + } + /* + * @private + */ + public int open() { + BusyIndicator.showWhile(null, new Runnable() { + public void run() { + access$superOpen(); + } + }); + return getReturnCode() ; + } + /** + * Refilters the current list according to the filter entered into the + * text edit field. + */ + protected void refilter() { + fSelectionList.filter(true); + } + /** + * If a empty-list message is set, a error message is shown + * Must be set before widget creation + */ + public void setEmptyListMessage(String message) { + fEmptyListMessage= message; + } + /** + * Sets the filter text to the given value. + */ + protected void setFilter(String text, boolean refilter) { + fSelectionList.setFilter(text, refilter); + } + /** + * Sets the message to be shown above the match text field. + * Must be set before widget creation + */ + public void setMessage(String message) { + fMessageText= message; + } + /** + * If the selection is empty, this message is shown + */ + public void setNothingSelectedMessage(String message) { + fNothingSelectedMessage= message; + } + /** + * Selects the elements in the list determined by the given + * selection indices. + */ + protected void setSelection(int[] selection) { + fSelectionList.setSelection(selection); + } + /** + * Initializes the selection list widget with the given list of + * elements. + */ + protected void setSelectionListElements(List elements, boolean refilter) { + fSelectionList.setElements(elements, refilter); + } + /** + * A validator can be set to check if the current selection + * is valid + */ + public void setValidator(ISelectionValidator validator) { + fValidator= validator; + } + /** + * Verifies the current selection and updates the status line + * accordingly. + */ + protected boolean verifyCurrentSelection() { + List sel= getWidgetSelection(); + int length= sel.size(); + if (length > 0) { + if (fValidator != null) { + fValidator.isValid(sel.toArray(), fCurrStatus); + } else { + fCurrStatus.setOK(); + } + } else { + if (isEmptyList()) { + fCurrStatus.setError(fEmptyListMessage); + } else { + fCurrStatus.setError(fNothingSelectedMessage); + } + } + updateStatus(fCurrStatus); + return fCurrStatus.isOK(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ElementListSelectionDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ElementListSelectionDialog.java new file mode 100644 index 00000000000..830e08ba5e6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ElementListSelectionDialog.java @@ -0,0 +1,114 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ILabelProvider; + +/** + * A class to select one or more elements out of an indexed property + */ +public class ElementListSelectionDialog extends AbstractElementListSelectionDialog { + + private List fElements; + + /* + * @private + */ + protected void computeResult() { + setResult(getWidgetSelection()); + } + /* + * @private + */ + protected Control createDialogArea(Composite parent) { + Control result= super.createDialogArea(parent); + + setSelectionListElements(fElements, false); + //a little trick to make the window come up faster + String initialFilter= null; + if (getPrimaryInitialSelection() instanceof String) + initialFilter= (String)getPrimaryInitialSelection(); + if (initialFilter != null) + setFilter(initialFilter, true); + else + refilter(); + + return result; + } + public Object getSelectedElement() { + return getPrimaryResult(); + } + public Object[] getSelectedElements() { + return getResult(); + } + /* + * @private + */ + protected void handleDoubleClick() { + if (verifyCurrentSelection()) { + buttonPressed(IDialogConstants.OK_ID); + } + } + /** + * Constructs a list selection dialog. + * @param renderer The label renderer used + * @param ignoreCase Decides if the match string ignores lower/upper case + * @param multipleSelection Allow multiple selection + */ + public ElementListSelectionDialog(Shell parent, String title, Image image, ILabelProvider renderer, boolean ignoreCase, boolean multipleSelection) { + super (parent, title, image, renderer, ignoreCase, multipleSelection); + } + /** + * Constructs a list selection dialog. + * @param renderer The label renderer used + * @param ignoreCase Decides if the match string ignores lower/upppr case + * @param multipleSelection Allow multiple selection + */ + public ElementListSelectionDialog(Shell parent, ILabelProvider renderer, boolean ignoreCase, boolean multipleSelection) { + this(parent, "", null, renderer, ignoreCase, multipleSelection); //$NON-NLS-1$ + } + public int open(Object[] elements) { + return open(Arrays.asList(elements)); + } + public int open(Object[] elements, String initialSelection) { + return open(Arrays.asList(elements), initialSelection); + } + /** + * Open the dialog. + * @param elements The elements to show in the list + * @return Returns OK or CANCEL + */ + public int open(List elements) { + setElements(elements); + return open(); + } + /** + * Open the dialog. + * @param elements The elements to show in the list + * @param initialSelection The initial content of the match text box. + * @return Returns OK or CANCEL + */ + public int open(List elements, String initialSelection) { + setElements(elements); + setInitialSelection(initialSelection); + return open(); + } + /** + * Sets the elements presented by this dialog. + */ + public void setElements(List elements) { + fElements= elements; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ISelectionValidator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ISelectionValidator.java new file mode 100644 index 00000000000..cf1849fa205 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/ISelectionValidator.java @@ -0,0 +1,10 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +public interface ISelectionValidator { + void isValid(Object[] selection, StatusInfo res); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/IStatusChangeListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/IStatusChangeListener.java new file mode 100644 index 00000000000..f8b0d90cd55 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/IStatusChangeListener.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IStatus; + +public interface IStatusChangeListener { + + /** + * Called to annonce that the given status has changed + */ + void statusChanged(IStatus status); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/MessageLine.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/MessageLine.java new file mode 100644 index 00000000000..d7e1cd53f6a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/MessageLine.java @@ -0,0 +1,126 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; + +/** + * A message line. It distinguishs between "normal" messages and errors. + * Setting an error message hides a currently displayed message until + * clearErrorMessage is called. + */ +public class MessageLine extends CLabel { + + private String fMessageText; + private String fErrorText; + + private Color fDefaultColor; + private RGB fErrorRGB; + private Color fErrorColor; + + private static RGB fgErrorRGB= new RGB(200, 0, 0); + + /** + * Clears the currently displayed error message and redisplayes + * the message which was active before the error message was set. + */ + public void clearErrorMessage() { + setErrorMessage(null); + } + /** + * Clears the currently displayed message. + */ + public void clearMessage() { + setMessage(null); + } + /** + * Get the currently displayed error text. + * @return The error message. If no error message is displayed null is returned. + */ + public String getErrorMessage() { + return fErrorText; + } + /** + * Get the currently displayed message. + * @return The message. If no message is displayed null is returned. + */ + public String getMessage() { + return fMessageText; + } + /** + * Creates a new message line as a child of the parent and with the given SWT stylebits. + * Error message will be shown with in the given rgb color. + */ + public MessageLine(Composite parent, int style, RGB errorRGB) { + super(parent, style); + fDefaultColor= getForeground(); + fErrorRGB= errorRGB; + } + /** + * Creates a new message line as a child of the parent and with the given SWT stylebits. + * Error message will be shown with in the rgb color 200,0,0. + */ + public MessageLine(Composite parent, int style) { + super(parent, style); + fDefaultColor= getForeground(); + fErrorRGB= fgErrorRGB; + } + /** + * Creates a new message line as a child of the given parent. + * Error message will be shown with in the rgb color 200,0,0. + */ + public MessageLine(Composite parent) { + this(parent, SWT.LEFT); + } + /** + * Sets the default error color used by all message lines. + * Note: a call to this method only affects newly created MessageLines not existing ones. + */ + public static void setErrorColor(RGB color) { + fgErrorRGB= color; + } + /** + * Display the given error message. A currently displayed message + * is saved and will be redisplayed when the error message is cleared. + */ + public void setErrorMessage(String message) { + fErrorText= message; + + if (message == null) { + setMessage(fMessageText); + } else { + if (fErrorColor == null) { + fErrorColor= new Color(getDisplay(), fErrorRGB); + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + fErrorColor.dispose(); + } + }); + } + setForeground(fErrorColor); + setText(message); + } + } + /** + * Set the message text. If the message line currently displays an error, + * the message is stored and will be shown after a call to clearErrorMessage + */ + public void setMessage(String message) { + fMessageText= message; + if (message == null) + message= ""; //$NON-NLS-1$ + if (fErrorText == null) { + setForeground(fDefaultColor); + setText(message); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionList.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionList.java new file mode 100644 index 00000000000..0e7c0e62bfd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionList.java @@ -0,0 +1,250 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.jface.viewers.ILabelProvider; + +import org.eclipse.cdt.internal.ui.util.StringMatcher; +import org.eclipse.cdt.internal.ui.util.TwoArrayQuickSort; + +/** + * A selection widget that consists of a list and a text entry field. The list + * of elements presented are limited to the pattern entered into the text entry + * field. + */ +public class SelectionList extends Composite { + + // State + private Object[] fElements; + private ILabelProvider fRenderer; + private boolean fIgnoreCase; + + // Implementation details + private String[] fRenderedStrings; + private int[] fFilteredElements; + private String fRememberedMatchText; + + // SWT widgets + private Table fList; + private Text fText; + + /** + * Adds a selection change listener to this widget. + */ + public void addSelectionListener(SelectionListener listener) { + fList.addSelectionListener(listener); + } + private void createList(int style) { + fList= new Table(this, style); + fList.setLayoutData(new GridData(GridData.FILL_BOTH)); + fList.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + fRenderer.dispose(); + } + }); + } + private void createText() { + fText= new Text(this, SWT.BORDER); + GridData spec= new GridData(); + spec.grabExcessVerticalSpace= false; + spec.grabExcessHorizontalSpace= true; + spec.horizontalAlignment= spec.FILL; + spec.verticalAlignment= spec.BEGINNING; + fText.setLayoutData(spec); + Listener l= new Listener() { + public void handleEvent(Event evt) { + filter(false); + } + }; + fText.addListener(SWT.Modify, l); + } + /** + * Filters the list of elements according to the pattern entered + * into the text entry field. + */ + public void filter(boolean forceUpdate) { + int k= 0; + String text= fText.getText(); + if (!forceUpdate && text.equals(fRememberedMatchText)) + return; + fRememberedMatchText= text; + StringMatcher matcher= new StringMatcher(text+"*", fIgnoreCase, false); //$NON-NLS-1$ + for (int i= 0; i < fElements.length; i++) { + if (matcher.match(fRenderedStrings[i])) { + fFilteredElements[k]= i; + k++; + } + } + fFilteredElements[k]= -1; + updateListWidget(fFilteredElements, k); + } + /** + * Returns the currently used filter text. + */ + public String getFilter() { + return fText.getText(); + } + /** + * Returns the selection indices. + */ + public int[] getSelectionIndices() { + return fList.getSelectionIndices(); + } + /** + * Returns a list of selected elements. Note that the type of the elements + * returned in the list are the same as the ones passed to the selection list + * via setElements. The list doesn't contain the rendered strings. + */ + public List getSelection() { + if (fList == null || fList.isDisposed() || fList.getSelectionCount() == 0) + return new ArrayList(0); + int[] listSelection= fList.getSelectionIndices(); + List selected= new ArrayList(listSelection.length); + for (int i= 0; i < listSelection.length; i++) { + selected.add(fElements[fFilteredElements[listSelection[i]]]); + } + return selected; + } + /** + * Returns true when the list of elements is empty. + */ + public boolean isEmptyList() { + return fElements == null || fElements.length == 0; + } + /** + * Creates new instance of the widget. + */ + public SelectionList(Composite parent, int style, ILabelProvider renderer, boolean ignoreCase) { + super(parent, SWT.NONE); + fRenderer= renderer; + fIgnoreCase= ignoreCase; + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; layout.marginWidth= 0; + //XXX: 1G9V58A: ITPUI:WIN2000 - Dialog.convert* methods should be static + setLayout(layout); + createText(); + createList(style); + } + /** + * Removes a selection change listener to this widget. + */ + public void removeSelectionListener(SelectionListener listener) { + fList.removeSelectionListener(listener); + } + private String[] renderStrings() { + String[] strings= new String[fElements.length]; + for (int i= 0; i < strings.length; i++) { + strings[i]= fRenderer.getText(fElements[i]); + } + TwoArrayQuickSort.sort(strings, fElements, fIgnoreCase); + return strings; + } + /** + * Select the pattern text. + */ + public void selectFilterText() { + fText.selectAll(); + } + /** + * Sets the list of elements presented in the widget. + */ + public void setElements(List elements, boolean refilter) { + // We copy the list since we sort it. + if (elements == null) + fElements= new Object[0]; + else + fElements= elements.toArray(); + fFilteredElements= new int[fElements.length+1]; + fRenderedStrings= renderStrings(); + if (refilter) + filter(true); + } + /* + * Non Java-doc + */ + public void setEnabled(boolean enable) { + super.setEnabled(enable); + fText.setEnabled(enable); + fList.setEnabled(enable); + } + /** + * Sets the filter pattern. Current only prefix filter pattern are supported. + */ + public void setFilter(String pattern, boolean refilter) { + fText.setText(pattern); + if (refilter) + filter(true); + } + /* + * Non Java-doc + */ + public boolean setFocus() { + return fText.setFocus(); + } + /* + * Non Java-doc + */ + public void setFont(Font font) { + super.setFont(font); + fText.setFont(font); + fList.setFont(font); + } + /** + * Selects the elements in the list determined by the given + * selection indices. + */ + protected void setSelection(int[] selection) { + fList.setSelection(selection); + } + private void updateListWidget(int[] indices, int size) { + if (fList == null || fList.isDisposed()) + return; + fList.setRedraw(false); + int itemCount= fList.getItemCount(); + if (size < itemCount) { + fList.remove(0, itemCount-size-1); + } + + TableItem[] items= fList.getItems(); + for (int i= 0; i < size; i++) { + TableItem ti= null; + if (i < itemCount) { + ti= items[i]; + } else { + ti= new TableItem(fList, i); + } + ti.setText(fRenderedStrings[indices[i]]); + Image img= fRenderer.getImage(fElements[indices[i]]); + if (img != null) + ti.setImage(img); + } + if (fList.getItemCount() > 0) { + fList.setSelection(0); + } + + fList.setRedraw(true); + Event event= new Event(); + fList.notifyListeners(SWT.Selection, event); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionStatusDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionStatusDialog.java new file mode 100644 index 00000000000..c371afac5ed --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/SelectionStatusDialog.java @@ -0,0 +1,187 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.ui.dialogs.SelectionDialog; + +import org.eclipse.core.runtime.IStatus; + +/** + * An abstract base class for dialogs with a status bar and ok/cancel buttons. + * The status message must be passed over as StatusInfo object and can be + * an error, warning or ok. The OK button is enabled / disabled depending + * on the status. + */ +public abstract class SelectionStatusDialog extends SelectionDialog { + + private MessageLine fStatusLine; + private IStatus fLastStatus; + private Image fImage; + private boolean fInitialSelectionSet; + private boolean fStatusLineAboveButtons= false; + + + /** + * Compute the result and return it. + */ + protected abstract void computeResult(); + /* (non-Javadoc) + * Method declared in Window. + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + if (fImage != null) + shell.setImage(fImage); + } + /* (non-Javadoc) + * Method declared in Dialog. + */ + protected Control createButtonBar(Composite parent) { + Composite composite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); + if (fStatusLineAboveButtons) { + layout.verticalSpacing= 0; + } else { + layout.numColumns= 2; + } + layout.marginHeight= 0; layout.marginWidth= 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + fStatusLine= new MessageLine(composite); + fStatusLine.setAlignment(SWT.LEFT); + fStatusLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + fStatusLine.setMessage(""); //$NON-NLS-1$ + + super.createButtonBar(composite); + return composite; + } + /* (non-Javadoc) + * Method declared in Dialog. + */ + public void create() { + super.create(); + if (fLastStatus != null) { + updateStatus(fLastStatus); + } + } + /** + * Returns the first element of the initial selection or null + * if there isn't any initial selection. + * @return the first element of the initial selection. + */ + protected Object getPrimaryInitialSelection() { + List result= getInitialSelections(); + if (result == null || result.size() == 0) + return null; + return result.get(0); + } + /** + * Returns the first element from the list of results. Returns null + * if no element has been selected. + * + * @return the first result element if one exists. Otherwise null is + * returned. + */ + public Object getPrimaryResult() { + Object[] result= getResult(); + if (result == null || result.length == 0) + return null; + return result[0]; + } + public SelectionStatusDialog(Shell parent) { + super(parent); + fInitialSelectionSet= false; + } + /* (non-Javadoc) + * Method declared in Dialog. + */ + protected void okPressed() { + computeResult(); + super.okPressed(); + } + /** + * Sets the image for this dialog. + * + * @param image the dialog's image + */ + public void setImage(Image image) { + fImage= image; + } + protected void setInitialSelection(int position, Object element) { + List l= getInitialSelections(); + l.set(position, element); + fInitialSelectionSet= true; + } + /** + * Sets the initial selection to the given element. + */ + public void setInitialSelection(Object element) { + // Allow clients to use set their own initial selection(s) + if (fInitialSelectionSet && element != null && element.equals("A")) //$NON-NLS-1$ + return; + + if (element != null) { + setInitialSelections(new Object[] { element }); + } else { + setInitialSelections(new Object[0]); + } + } + public void setInitialSelections(Object[] selectedElements) { + super.setInitialSelections(selectedElements); + fInitialSelectionSet= true; + } + /** + * Sets a result element at the given position. + */ + protected void setResult(int position, Object element) { + Object[] result= getResult(); + result[position]= element; + setResult(Arrays.asList(result)); + } + /** + * Controls whether status line appears to the left of the buttons (default) + * or above them. + * + * @param aboveButtons if true status line is placed above buttons; if + * false to the right + */ + public void setStatusLineAboveButtons(boolean aboveButtons) { + fStatusLineAboveButtons= aboveButtons; + } + /** + * Update the status of the ok button to reflect the given status. Subclasses + * may override this method to update additional buttons. + */ + protected void updateButtonsEnableState(IStatus status) { + Button okButton= getOkButton(); + if (okButton != null && !okButton.isDisposed()) + okButton.setEnabled(!status.matches(IStatus.ERROR)); + } + /** + * Update the dialog's status line to reflect the given status. It is safe to call + * this method before the dialog has been opened. + */ + protected void updateStatus(IStatus status) { + fLastStatus= status; + if (fStatusLine != null && !fStatusLine.isDisposed()) { + updateButtonsEnableState(status); + StatusTool.applyToStatusLine(fStatusLine, status); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusDialog.java new file mode 100644 index 00000000000..7064e0caaab --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusDialog.java @@ -0,0 +1,163 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; + +import org.eclipse.core.runtime.IStatus; + +/** + * An abstract base class for dialogs with a status bar and ok/cancel buttons. + * The status message must be passed over as StatusInfo object and can be + * an error, warning or ok. The OK button is enabled or disabled depending + * on the status. + */ +public abstract class StatusDialog extends Dialog { + + private Button fOkButton; + private MessageLine fStatusLine; + private IStatus fLastStatus; + private String fTitle; + private Image fImage; + + private boolean fStatusLineAboveButtons; + + /** + * Creates an instane of a status dialog. + */ + public StatusDialog(Shell parent) { + super(parent); + fStatusLineAboveButtons= false; + } + + /** + * Specifies whether status line appears to the left of the buttons (default) + * or above them. + * + * @param aboveButtons if true status line is placed above buttons; if + * false to the right + */ + public void setStatusLineAboveButtons(boolean aboveButtons) { + fStatusLineAboveButtons= aboveButtons; + } + + /** + * Update the dialog's status line to reflect the given status. + * It is save to call this method before the dialog has been opened. + */ + protected void updateStatus(IStatus status) { + fLastStatus= status; + if (fStatusLine != null && !fStatusLine.isDisposed()) { + updateButtonsEnableState(status); + fStatusLine.setErrorMessage(status.getMessage()); + } + } + + /** + * Returns the last status. + */ + public IStatus getStatus() { + return fLastStatus; + } + + /** + * Updates the status of the ok button to reflect the given status. + * Subclasses may override this method to update additional buttons. + * @param status the status. + */ + protected void updateButtonsEnableState(IStatus status) { + if (fOkButton != null && !fOkButton.isDisposed()) + fOkButton.setEnabled(!status.matches(IStatus.ERROR)); + } + + /* + * @see Window#create(Shell) + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + if (fTitle != null) + shell.setText(fTitle); + } + + /* + * @see Window#create() + */ + public void create() { + super.create(); + if (fLastStatus != null) { + // policy: dialogs are not allowed to come up with an error message + if (fLastStatus.matches(IStatus.ERROR)) { + StatusInfo status= new StatusInfo(); + status.setError(""); //$NON-NLS-1$ + fLastStatus= status; + } + updateStatus(fLastStatus); + } + } + + /* + * @see Dialog#createButtonsForButtonBar(Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + fOkButton= createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + /* + * @see Dialog#createButtonBar(Composite) + */ + protected Control createButtonBar(Composite parent) { + Composite composite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); + layout.numColumns= 1; + layout.marginHeight= 0; + layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + fStatusLine= new MessageLine(composite); + fStatusLine.setAlignment(SWT.LEFT); + fStatusLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + fStatusLine.setErrorMessage(null); //$NON-NLS-1$ + + super.createButtonBar(composite); + return composite; + } + + /** + * Sets the title for this dialog. + * @param title the title. + */ + public void setTitle(String title) { + fTitle= title != null ? title : ""; //$NON-NLS-1$ + Shell shell= getShell(); + if ((shell != null) && !shell.isDisposed()) + shell.setText(fTitle); + } + + /** + * Sets the image for this dialog. + * @param image the image. + */ + public void setImage(Image image) { + fImage= image; + Shell shell= getShell(); + if ((shell != null) && !shell.isDisposed()) + shell.setImage(fImage); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusInfo.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusInfo.java new file mode 100644 index 00000000000..84b6cc354ba --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusInfo.java @@ -0,0 +1,102 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.cdt.internal.CCorePlugin; + +/** + * A settable IStatus + * Can be an error, warning, info or ok. For error, info and warning states, + * a message describes the problem + */ +public class StatusInfo implements IStatus { + + private String fStatusMessage; + private int fSeverity; + + /** + * @see IStatus#getChildren() + */ + public IStatus[] getChildren() { + return new IStatus[0]; + } + /** + * @see IStatus#getCode() + */ + public int getCode() { + return fSeverity; + } + /** + * @see IStatus#getException() + */ + public Throwable getException() { + return null; + } + /** + * @see IStatus#getMessage + */ + public String getMessage() { + return fStatusMessage; + } + /** + * @see IStatus#getPlugin() + */ + public String getPlugin() { + return CCorePlugin.PLUGIN_ID; + } + /** + * @see IStatus#getSeverity() + */ + public int getSeverity() { + return fSeverity; + } + public boolean isError() { + return fSeverity == IStatus.ERROR; + } + public boolean isInfo() { + return fSeverity == IStatus.INFO; + } + /** + * @see IStatus#isMultiStatus() + */ + public boolean isMultiStatus() { + return false; + } + public boolean isOK() { + return fSeverity == IStatus.OK; + } + public boolean isWarning() { + return fSeverity == IStatus.WARNING; + } + /** + * @see IStatus#matches(int) + */ + public boolean matches(int severityMask) { + return (fSeverity & severityMask) != 0; + } + public void setError(String errorMessage) { + fStatusMessage= errorMessage; + fSeverity= IStatus.ERROR; + } + public void setInfo(String infoMessage) { + fStatusMessage= infoMessage; + fSeverity= IStatus.INFO; + } + public void setOK() { + fStatusMessage= null; + fSeverity= IStatus.OK; + } + public void setWarning(String warningMessage) { + fStatusMessage= warningMessage; + fSeverity= IStatus.WARNING; + } + public StatusInfo() { + fStatusMessage= null; + fSeverity= OK; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusTool.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusTool.java new file mode 100644 index 00000000000..89471bedd91 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/StatusTool.java @@ -0,0 +1,73 @@ +package org.eclipse.cdt.internal.ui.dialogs; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.jface.dialogs.DialogPage; + +public class StatusTool { + + /** + * Applies the status to the status line of a dialog page + */ + public static void applyToStatusLine(MessageLine messageLine, IStatus status) { + String[] messages= getErrorMessages(status); + messageLine.setErrorMessage(messages[0]); + messageLine.setMessage(messages[1]); + } + /** + * Applies the status to the status line of a dialog page + */ + public static void applyToStatusLine(DialogPage page, IStatus status) { + String[] messages= getErrorMessages(status); + page.setErrorMessage(messages[0]); + page.setMessage(messages[1]); + } + /** + * Returns error-message / warning-message for a status + */ + public static String[] getErrorMessages(IStatus status) { + String message= status.getMessage(); + if (status.matches(IStatus.ERROR) && !"".equals(message)) { //$NON-NLS-1$ + return new String[] { message, null }; + } else if (status.matches(IStatus.WARNING | IStatus.INFO)) { + return new String[] { null, message }; + } else { + return new String[] { null, null }; + } + } + /** + * Compare two IStatus. The more severe is returned: + * An error is more severe than a warning, and a warning is more severe + * than ok. + */ + public static IStatus getMoreSevere(IStatus s1, IStatus s2) { + if (s1.getSeverity() > s2.getSeverity()) { + return s1; + } else { + return s2; + } + } + /** + * Finds the most severe status from a array of status + * An error is more severe than a warning, and a warning is more severe + * than ok. + */ + public static IStatus getMostSevere(IStatus[] status) { + IStatus max= null; + for (int i= 0; i < status.length; i++) { + IStatus curr= status[i]; + if (curr.matches(IStatus.ERROR)) { + return curr; + } + if (max == null || curr.getSeverity() > max.getSeverity()) { + max= curr; + } + } + return max; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java new file mode 100644 index 00000000000..98d19615368 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeOnSelectionAction.java @@ -0,0 +1,190 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CCompletionContributorManager; +import org.eclipse.cdt.internal.ui.CFileElementWorkingCopy; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.codemanipulation.AddIncludeOperation; +import org.eclipse.cdt.ui.IFunctionSummary; +import org.eclipse.cdt.ui.IRequiredInclude; +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.IUpdate; + + +public class AddIncludeOnSelectionAction extends Action implements IUpdate { + + private ITextEditor fEditor; + + + public AddIncludeOnSelectionAction() { + this(null); + } + public AddIncludeOnSelectionAction(ITextEditor editor) { + super(CEditorMessages.getString("AddIncludeOnSelection.label")); //$NON-NLS-1$ + setToolTipText(CEditorMessages.getString("AddIncludeOnSelection.tooltip")); //$NON-NLS-1$ + setDescription(CEditorMessages.getString("AddIncludeOnSelection.description")); //$NON-NLS-1$ + + fEditor= editor; + //WorkbenchHelp.setHelp(this, new Object[] { IJavaHelpContextIds.ADD_IMPORT_ON_SELECTION_ACTION }); + } + private void addInclude(IRequiredInclude[] inc, CFileElementWorkingCopy tu) { + AddIncludeOperation op= new AddIncludeOperation(fEditor, tu, inc, false); + try { + ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell()); + dialog.run(false, true, op); + } catch (InvocationTargetException e) { + e.printStackTrace(); + MessageDialog.openError(getShell(), CEditorMessages.getString("AddIncludeOnSelection.error.message1"), e.getTargetException().getMessage()); //$NON-NLS-1$ + } catch (InterruptedException e) { + // Do nothing. Operation has been canceled. + } + } + + private CFileElementWorkingCopy getTranslationUnit () { + CFileElementWorkingCopy unit = null; + if(fEditor != null) { + IEditorInput editorInput= (IEditorInput)fEditor.getEditorInput(); + IDocumentProvider provider= fEditor.getDocumentProvider(); + try { + if (editorInput instanceof IFileEditorInput) + unit = new CFileElementWorkingCopy((IFileEditorInput)editorInput, provider); + else if (editorInput instanceof IStorageEditorInput) + unit = new CFileElementWorkingCopy((IStorageEditorInput)editorInput, provider); + else + throw new CoreException(new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, 0, "no Editor Input", null)); + + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + } + } + return unit; + } + + protected Shell getShell() { + return fEditor.getSite().getShell(); + } + + private int getNameStart(IDocument doc, int pos) throws BadLocationException { + if (pos > 0 && doc.getChar(pos - 1) == '.') { + pos--; + while (pos > 0) { + char ch= doc.getChar(pos - 1); + if (!Character.isJavaIdentifierPart(ch) && ch != '.') { + return pos; + } + pos--; + } + } + return pos; + } + +/* private void removeQualification(IDocument doc, int nameStart, IType type) throws BadLocationException { + String packName= type.getPackageFragment().getElementName(); + int packLen= packName.length(); + if (packLen > 0) { + for (int k= 0; k < packLen; k++) { + if (doc.getChar(nameStart + k) != packName.charAt(k)) { + return; + } + } + doc.replace(nameStart, packLen + 1, ""); //$NON-NLS-1$ + } + } */ + /** + * @see IAction#actionPerformed + */ + public void run() { + + CFileElementWorkingCopy tu= getTranslationUnit(); + if (tu != null) { + ISelection s= fEditor.getSelectionProvider().getSelection(); + IDocument doc= fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput()); + if (!s.isEmpty() && doc != null) { + ITextSelection selection= (ITextSelection) s; + try { + int selStart= selection.getOffset(); + int nameStart= getNameStart(doc, selStart); + int len= selStart - nameStart + selection.getLength(); + + String name= doc.get(nameStart, len).trim(); + + //IType[] types= StubUtility.findAllTypes(typeName, cu.getJavaProject(), null); + //IType chosen= selectResult(types, packName, getShell()); + IFunctionSummary fs = CCompletionContributorManager.getDefault().getFunctionInfo(name); + if(fs != null) { + IRequiredInclude[] ri = fs.getIncludes(); + if(ri != null && ri.length > 0) { + addInclude(ri, tu); + return; + } + } + } catch (BadLocationException e) { + MessageDialog.openError(getShell(), CEditorMessages.getString("AddIncludeOnSelection.error.message3"), CEditorMessages.getString("AddIncludeOnSelection.error.message4") + e.getMessage()); //$NON-NLS-2$ //$NON-NLS-1$ + } + } + } + getShell().getDisplay().beep(); + } +/* private IType selectResult(IType[] results, String packName, Shell shell) { + int nResults= results.length; + + if (nResults == 0) { + return null; + } else if (nResults == 1) { + return results[0]; + } + + if (packName.length() != 0) { + for (int i= 0; i < results.length; i++) { + IType curr= (IType) results[i]; + if (packName.equals(curr.getPackageFragment().getElementName())) { + return curr; + } + } + } + + JavaPlugin plugin= JavaPlugin.getDefault(); + + int flags= (JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_CONTAINER_QUALIFICATION); + ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(flags), true, false); + dialog.setTitle(JavaEditorMessages.getString("AddImportOnSelection.dialog.title")); //$NON-NLS-1$ + dialog.setMessage(JavaEditorMessages.getString("AddImportOnSelection.dialog.message")); //$NON-NLS-1$ + if (dialog.open(results) == dialog.OK) { + return (IType) dialog.getSelectedElement(); + } + return null; + } */ + public void setContentEditor(ITextEditor editor) { + fEditor= editor; + } + public void update() { + ISelection selection= fEditor.getSelectionProvider().getSelection(); + setEnabled(!selection.isEmpty()); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/BracketPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/BracketPainter.java new file mode 100644 index 00000000000..dfaf069ca2f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/BracketPainter.java @@ -0,0 +1,169 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.cdt.internal.ui.text.CPairMatcher; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.ISourceViewer; + + + + +public final class BracketPainter implements IPainter, PaintListener { + + private CPairMatcher fMatcher= new CPairMatcher(new char[] { '{', '}', '(', ')', '[', ']' }); + private Position fBracketPosition= new Position(0, 0); + private int fAnchor; + + private boolean fIsActive= false; + private ISourceViewer fSourceViewer; + private StyledText fTextWidget; + private Color fColor; + private boolean fNoBox; + + private IPositionManager fPositionManager; + + + public BracketPainter(ISourceViewer sourceViewer) { + fSourceViewer= sourceViewer; + fTextWidget= sourceViewer.getTextWidget(); + } + + public void setHighlightColor(Color color) { + fColor= color; + } + + public void setHighlightStyle(boolean nobox) { + fNoBox = nobox; + } + + public void dispose() { + if (fMatcher != null) { + fMatcher.dispose(); + fMatcher= null; + } + + fColor= null; + fTextWidget= null; + } + + public void deactivate(boolean redraw) { + if (fIsActive) { + fIsActive= false; + fTextWidget.removePaintListener(this); + if (fPositionManager != null) + fPositionManager.removeManagedPosition(fBracketPosition); + if (redraw) + handleDrawRequest(null); + } + } + + public void paintControl(PaintEvent event) { + if (fTextWidget != null) + handleDrawRequest(event.gc); + } + + private void handleDrawRequest(GC gc) { + + if (fBracketPosition.isDeleted) + return; + + int length= fBracketPosition.getLength(); + if (length < 1) + return; + + int offset= fBracketPosition.getOffset(); + IRegion region= fSourceViewer.getVisibleRegion(); + + if (region.getOffset() <= offset && region.getOffset() + region.getLength() >= offset + length) { + offset -= region.getOffset(); + if (fMatcher.RIGHT == fAnchor) + draw(gc, offset, 1); + else + draw(gc, offset + length -1, 1); + } + } + + private void draw(GC gc, int offset, int length) { + if (gc != null) { + Point left= fTextWidget.getLocationAtOffset(offset); + Point right= fTextWidget.getLocationAtOffset(offset + length); + + gc.setForeground(fColor); + if(fNoBox) { + gc.drawString(fTextWidget.getTextRange(offset, 1), left.x, left.y); + } else { + gc.drawRectangle(left.x, left.y, right.x - left.x - 1, gc.getFontMetrics().getHeight() - 1); + } + } else { + fTextWidget.redrawRange(offset, length, true); + } + } + + /* + * @see IPainter#paint(int) + */ + public void paint(int reason) { + Point selection= fSourceViewer.getSelectedRange(); + if (selection.y > 0) { + deactivate(true); + return; + } + + IRegion pair= fMatcher.match(fSourceViewer.getDocument(), selection.x); + if (pair == null) { + deactivate(true); + return; + } + + if (fIsActive) { + // only if different + if (pair.getOffset() != fBracketPosition.getOffset() || + pair.getLength() != fBracketPosition.getLength() || + fMatcher.getAnchor() != fAnchor) { + + // remove old highlighting + handleDrawRequest(null); + // update position + fBracketPosition.isDeleted= false; + fBracketPosition.offset= pair.getOffset(); + fBracketPosition.length= pair.getLength(); + fAnchor= fMatcher.getAnchor(); + // apply new highlighting + handleDrawRequest(null); + + } + } else { + + fIsActive= true; + + fBracketPosition.isDeleted= false; + fBracketPosition.offset= pair.getOffset(); + fBracketPosition.length= pair.getLength(); + fAnchor= fMatcher.getAnchor(); + + fTextWidget.addPaintListener(this); + fPositionManager.addManagedPosition(fBracketPosition); + handleDrawRequest(null); + } + } + + /* + * @see IPainter#setPositionManager(IPositionManager) + */ + public void setPositionManager(IPositionManager manager) { + fPositionManager= manager; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java new file mode 100644 index 00000000000..9972005b13f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java @@ -0,0 +1,260 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; + +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.util.ListenerList; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; + +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.part.Page; +import org.eclipse.ui.texteditor.IDocumentProvider; + +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.IStatus; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.CFileElementWorkingCopy; +import org.eclipse.cdt.internal.ui.StandardCElementLabelProvider; +import org.eclipse.cdt.internal.ui.CContentProvider; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; + +public class CContentOutlinePage extends Page implements IContentOutlinePage, ISelectionChangedListener { + private CEditor fEditor; + private CFileElementWorkingCopy fInput; + private ProblemTreeViewer treeViewer; + private ListenerList selectionChangedListeners = new ListenerList(); + + private OpenIncludeAction fOpenIncludeAction; + private SearchForReferencesAction fSearchForReferencesAction; + + public CContentOutlinePage(CEditor editor) { + super(); + fEditor= editor; + fInput= null; + + fOpenIncludeAction= new OpenIncludeAction(this); + fSearchForReferencesAction= new SearchForReferencesAction(this); + } + + public ICElement getRoot() { + return fInput; + } + + /** + * Called by the editor to signal that the content has updated. + */ + public void contentUpdated() { + if (fInput != null) { + try { + fInput.update(); + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + fInput= null; + return; + } + + final TreeViewer treeViewer= getTreeViewer(); + if (treeViewer != null && !treeViewer.getControl().isDisposed()) { + treeViewer.getControl().getDisplay().asyncExec(new Runnable() { + public void run() { + if (!treeViewer.getControl().isDisposed()) { + ISelection sel= treeViewer.getSelection(); + treeViewer.getControl().setRedraw(false); + treeViewer.refresh(); + treeViewer.setSelection(updateSelection(sel)); + treeViewer.getControl().setRedraw(true); + } + } + }); + } + } + } + + private ISelection updateSelection(ISelection sel) { + ArrayList newSelection= new ArrayList(); + if (sel instanceof IStructuredSelection) { + Iterator iter= ((IStructuredSelection)sel).iterator(); + for (;iter.hasNext();) { + //ICElement elem= fInput.findEqualMember((ICElement)iter.next()); + ICElement elem = (ICElement)iter.next(); + if (elem != null) { + newSelection.add(elem); + } + } + } + return new StructuredSelection(newSelection); + } + + /** + * called to create the context menu of the outline + */ + private void contextMenuAboutToShow(IMenuManager menu) { + if (OpenIncludeAction.canActionBeAdded(getSelection())) { + menu.add(fOpenIncludeAction); + } + if (SearchForReferencesAction.canActionBeAdded(getSelection())) { + menu.add(fSearchForReferencesAction); + } + } + + /** + * @see ContentOutlinePage#createControl + */ + public void createControl(Composite parent) { + treeViewer = new ProblemTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + treeViewer.addSelectionChangedListener(this); + + //treeViewer.setContentProvider(new CModelContentProvider()); + treeViewer.setContentProvider(new CContentProvider(true, true)); + treeViewer.setLabelProvider(new StandardCElementLabelProvider()); + treeViewer.setAutoExpandLevel(treeViewer.ALL_LEVELS); + treeViewer.addSelectionChangedListener(this); + + CPlugin.getDefault().getProblemMarkerManager().addListener(treeViewer); + + MenuManager manager= new MenuManager("#PopUp"); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + contextMenuAboutToShow(manager); + } + }); + Control control= treeViewer.getControl(); + Menu menu= manager.createContextMenu(control); + control.setMenu(menu); + + //IFileEditorInput editorInput= (IFileEditorInput)fEditor.getEditorInput(); + IEditorInput editorInput= (IEditorInput)fEditor.getEditorInput(); + IDocumentProvider provider= fEditor.getDocumentProvider(); + try { + if (editorInput instanceof IFileEditorInput) + //fInput = ((CPlugin.ElementFactory)plugin.getCCore()).createWorkingCopy((IFileEditorInput)editorInput, provider); + fInput = new CFileElementWorkingCopy((IFileEditorInput)editorInput, provider); + else if (editorInput instanceof IStorageEditorInput) + //fInput = ((CPlugin.ElementFactory)plugin.getCCore()).createWorkingCopy((IStorageEditorInput)editorInput, provider); + fInput = new CFileElementWorkingCopy((IStorageEditorInput)editorInput, provider); + else + throw new CoreException(new Status(IStatus.ERROR, CPlugin.PLUGIN_ID, 0, "no Editor Input", null)); + + treeViewer.setInput(fInput); + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + fInput= null; + } + } + + public void dispose() { + CPlugin.getDefault().getProblemMarkerManager().removeListener(treeViewer); + super.dispose(); + } + + /** + * @see IPage#setActionBars(IActionBars) + */ + public void setActionBars(IActionBars actionBars) { + IToolBarManager toolBarManager= actionBars.getToolBarManager(); + + LexicalSortingAction action= new LexicalSortingAction(getTreeViewer()); + toolBarManager.add(action); + } + + /* (non-Javadoc) + * Method declared on ISelectionProvider. + */ + public void addSelectionChangedListener(ISelectionChangedListener listener) { + selectionChangedListeners.add(listener); + } + + /** + * Fires a selection changed event. + * + * @param selction the new selection + */ + protected void fireSelectionChanged(ISelection selection) { + // create an event + SelectionChangedEvent event = new SelectionChangedEvent(this, selection); + + // fire the event + Object[] listeners = selectionChangedListeners.getListeners(); + for (int i = 0; i < listeners.length; ++i) { + ((ISelectionChangedListener) listeners[i]).selectionChanged(event); + } + } + /* (non-Javadoc) + * Method declared on IPage (and Page). + */ + public Control getControl() { + if (treeViewer == null) + return null; + return treeViewer.getControl(); + } + /* (non-Javadoc) + * Method declared on ISelectionProvider. + */ + public ISelection getSelection() { + if (treeViewer == null) + return StructuredSelection.EMPTY; + return treeViewer.getSelection(); + } + /** + * Returns this page's tree viewer. + * + * @return this page's tree viewer, or null if + * createControl has not been called yet + */ + protected TreeViewer getTreeViewer() { + return treeViewer; + } + /* (non-Javadoc) + * Method declared on ISelectionProvider. + */ + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + selectionChangedListeners.remove(listener); + } + /* (non-Javadoc) + * Method declared on ISelectionChangeListener. + * Gives notification that the tree selection has changed. + */ + public void selectionChanged(SelectionChangedEvent event) { + fireSelectionChanged(event.getSelection()); + } + /** + * Sets focus to a part in the page. + */ + public void setFocus() { + treeViewer.getControl().setFocus(); + } + /* (non-Javadoc) + * Method declared on ISelectionProvider. + */ + public void setSelection(ISelection selection) { + if (treeViewer != null) + treeViewer.setSelection(selection); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java new file mode 100644 index 00000000000..f388f457443 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java @@ -0,0 +1,129 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; + + +import org.eclipse.jface.text.DefaultLineTracker; +import org.eclipse.jface.text.GapTextStore; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.source.IAnnotationModel; + + +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.editors.text.FileDocumentProvider; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.eclipse2.CAbstractDocument; +import org.eclipse.cdt.internal.ui.text.eclipse2.IDocumentExtension; + +public class CDocumentProvider extends FileDocumentProvider { + + static private class RegisteredReplace { + IDocumentListener fOwner; + IDocumentExtension.IReplace fReplace; + + RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { + fOwner= owner; + fReplace= replace; + } + }; + /** + * Bundle of all required informations to allow working copy management. + */ + protected class CDocument extends CAbstractDocument { + + /** + * Creates a new empty document. + */ + public CDocument() { + super(); + setTextStore(new GapTextStore(50, 300)); + setLineTracker(new DefaultLineTracker()); + completeInitialization(); + } + + /** + * Creates a new document with the given initial content. + * + * @param initialContent the document's initial content + */ + public CDocument(String initialContent) { + super(); + setTextStore(new GapTextStore(50, 300)); + setLineTracker(new DefaultLineTracker()); + getStore().set(initialContent); + getTracker().set(initialContent); + completeInitialization(); + } + }; + + /** + * @see AbstractDocumentProvider#createDocument(Object) + */ + protected IDocument createDocument(Object element) throws CoreException { + IDocument document; + + if (element instanceof IStorageEditorInput) { + IStorage storage= ((IStorageEditorInput) element).getStorage(); + + document= new CDocument(); + setDocumentContent(document, storage.getContents()); + } else { + return null; + } + //IDocument document= super.createDocument(element); + if (document != null) { + IDocumentPartitioner partitioner= CPlugin.getDefault().getTextTools().createDocumentPartitioner(); + partitioner.connect(document); + document.setDocumentPartitioner(partitioner); + } + return document; + } + + /* + * @see AbstractDocumentProvider#createAnnotationModel(Object) + */ + protected IAnnotationModel createAnnotationModel(Object element) throws CoreException { + if (element instanceof IFileEditorInput) { + IFileEditorInput input= (IFileEditorInput) element; + return new CMarkerAnnotationModel(input.getFile()); + } + + return super.createAnnotationModel(element); + } + + protected ElementInfo createeeElementInfo(Object element) throws CoreException { + if (element instanceof IFileEditorInput) { + + IFileEditorInput input= (IFileEditorInput) element; + + try { + input.getFile().refreshLocal(IResource.DEPTH_INFINITE, null); + } catch (CoreException x) { + handleCoreException(x,"CFileDocumentProvider.createElementInfo"); //$NON-NLS-1$ + } + + IDocument d= createDocument(element); + IAnnotationModel m= new CMarkerAnnotationModel(((IFileEditorInput)element).getFile()); + FileSynchronizer f= new FileSynchronizer(input); + f.install(); + + FileInfo info= new FileInfo(d, m, f); + info.fModificationStamp= computeModificationStamp(input.getFile()); + + return info; + } + + return super.createElementInfo(element); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java new file mode 100644 index 00000000000..d31e12b90d3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -0,0 +1,1642 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IPluginRegistry; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.custom.ST; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorActionBarContributor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IPartService; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.dialogs.SaveAsDialog; +import org.eclipse.ui.part.EditorActionBarContributor; +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.ui.texteditor.DefaultRangeIndicator; +import org.eclipse.ui.texteditor.IStatusField; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.MarkerAnnotation; +import org.eclipse.ui.texteditor.MarkerUtilities; +import org.eclipse.ui.texteditor.TextOperationAction; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.ui.views.tasklist.TaskList; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.IContextMenuConstants; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.eclipse2.ITextViewerExtension; +import org.eclipse.cdt.ui.ICDTConstants; +import org.eclipse.cdt.ui.ICEditorContextMenuAction; +import org.eclipse.cdt.ui.ICEditorRulerAction; +/** + * C specific text editor. + */ +public class CEditor extends AbstractTextEditor implements ISelectionChangedListener { + + + /** The outline page */ + protected CContentOutlinePage fOutlinePage; + + private ICEditorContextMenuAction[] fEditorActions; +// private HashMap fEditorActionPaths = new HashMap( 5 ); + private ICEditorRulerAction[] fRulerActions; + private IAction fRulerSingleclickAction; + private SearchForReferencesAction fSearchForReferencesAction; + + /** Status bar fields -- @@@ gone with Eclipse 2.0 */ + private Map fStatusFields; + private boolean fInserting= true; + + /** The editor's foreground color -- gone in 2.0 */ + private Color fForegroundColor; + /** The editor's background color */ + private Color fBackgroundColor; + + + protected ISelectionChangedListener fStatusLineClearer; + + /** The editor's paint manager */ + private PaintManager fPaintManager; + /** The editor's bracket painter */ + private BracketPainter fBracketPainter; + /** The editor's line painter */ + private LinePainter fLinePainter; + /** The editor's problem painter */ + private ProblemPainter fProblemPainter; + /** The editor's print margin ruler painter */ + private PrintMarginPainter fPrintMarginPainter; + /** The editor's tab converter */ + private TabConverter fTabConverter; + + /** Listener to annotation model changes that updates the error tick in the tab image */ + private CEditorErrorTickUpdater fCEditorErrorTickUpdater; + + + /* Preference key line color shading */ + public final static String CURRENT_LINE= "CEditor.currentLine"; + /* Preference key for color of shading */ + public final static String CURRENT_LINE_COLOR= "CEditor.currentLineColor"; + /* Preference key for matching brackets */ + public final static String MATCHING_BRACKETS= "matchingBrackets"; + /* Preference key for matching brackets color */ + public final static String MATCHING_BRACKETS_COLOR= "matchingBracketsColor"; + /* Preference key for matching brackets color */ + public final static String MATCHING_BRACKETS_NOBOX= "matchingBracketsNobox"; + /* Preference key for matching brackets color */ + public final static String PREFERENCE_COLOR_BACKGROUND = "CEditor.preferenceColorBackground"; + /* Preference key for matching brackets color */ + public final static String PREFERENCE_COLOR_FOREGROUND = "CEditor.preferenceColorForeground"; + /* Preference key for matching brackets color */ + public final static String PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT = "CEditor.preferenceColorBackgroundDefault"; + /* Preference key for matching brackets color */ + public final static String PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT = "CEditor.preferenceColorForegroundDefault"; + /** Preference key for problem indication */ + public final static String PROBLEM_INDICATION= "problemIndication"; + /** Preference key for problem highlight color */ + public final static String PROBLEM_INDICATION_COLOR= "problemIndicationColor"; + /** Preference key for showing print marging ruler */ + public final static String PRINT_MARGIN= "printMargin"; + /** Preference key for print margin ruler color */ + public final static String PRINT_MARGIN_COLOR= "printMarginColor"; + /** Preference key for print margin ruler column */ + public final static String PRINT_MARGIN_COLUMN= "printMarginColumn"; + /** Preference key for inserting spaces rather than tabs */ + public final static String SPACES_FOR_TABS= "spacesForTabs"; + /** Preference key for linked position color */ + public final static String LINKED_POSITION_COLOR= "linkedPositionColor"; //$NON-NLS-1$ + + /** + * Default constructor. + */ + public CEditor() { + super(); + CTextTools textTools= CPlugin.getDefault().getTextTools(); + setSourceViewerConfiguration(new CSourceViewerConfiguration(textTools, this)); + setDocumentProvider(CPlugin.getDefault().getDocumentProvider()); + setRangeIndicator(new DefaultRangeIndicator()); + setPreferenceStore(CPlugin.getDefault().getPreferenceStore()); + + fCEditorErrorTickUpdater= new CEditorErrorTickUpdater(this); + + } + + /** + * @see AbstractTextEditor#doSetInput(IEditorInput) + */ + protected void doSetInput(IEditorInput input) throws CoreException { + super.doSetInput(input); + fCEditorErrorTickUpdater.setAnnotationModel(getDocumentProvider().getAnnotationModel(input)); + } + + /** + * Update the title image + */ + public void updatedTitleImage(Image image) { + setTitleImage(image); + } + + + /** + * @see IEditorPart#init(IWorkbenchPartSite, Object) + */ + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + //if (!(input instanceof IFileEditorInput)) { + // throw new PartInitException(CPlugin.getResourceString("Editor.error.invalid_input")); + //} + super.init(site, input); + } + + + /** + * Gets the current input + */ + public IFile getInputFile() { + //IFileEditorInput editorInput = (IFileEditorInput)getEditorInput(); + IEditorInput editorInput= (IEditorInput)getEditorInput(); + if (editorInput != null) { + if ((editorInput instanceof IFileEditorInput)) { + return ((IFileEditorInput)editorInput).getFile(); + } + } + return null; + } + + + public boolean isSaveAsAllowed() { + return true; + } + /* + * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors. + * Changed behavior to make sure that if called inside a regular save (because + * of deletion of input element) there is a way to report back to the caller. + */ + protected void performSaveAs(IProgressMonitor progressMonitor) { + + Shell shell= getSite().getShell(); + + SaveAsDialog dialog= new SaveAsDialog(shell); + if (dialog.open() == Dialog.CANCEL) { + if (progressMonitor != null) + progressMonitor.setCanceled(true); + return; + } + + IPath filePath= dialog.getResult(); + if (filePath == null) { + if (progressMonitor != null) + progressMonitor.setCanceled(true); + return; + } + + filePath= filePath.removeTrailingSeparator(); + IPath folderPath= filePath.removeLastSegments(1); + if (folderPath == null) { + if (progressMonitor != null) + progressMonitor.setCanceled(true); + return; + } + + IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot(); + + /* + * 1GF7WG9: ITPJUI:ALL - EXCEPTION: "Save As..." always fails + */ + + IFile file= root.getFile(filePath); + final FileEditorInput newInput= new FileEditorInput(file); + + WorkspaceModifyOperation op= new WorkspaceModifyOperation() { + public void execute(final IProgressMonitor monitor) throws CoreException { + + /* + * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there + * Changed false to true. + */ + getDocumentProvider().saveDocument(monitor, newInput, getDocumentProvider().getDocument(getEditorInput()), true); + } + }; + + boolean success= false; + try { + + getDocumentProvider().aboutToChange(newInput); + + new ProgressMonitorDialog(shell).run(false, true, op); + setInput(newInput); + success= true; + + } catch (InterruptedException x) { + } catch (InvocationTargetException x) { + + /* + * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there + * Missing resources. + */ + Throwable t= x.getTargetException(); + if (t instanceof CoreException) { + CoreException cx= (CoreException) t; + ErrorDialog.openError(shell, CEditorMessages.getString("CEditor.error.saving.title2"), CEditorMessages.getString("CEditor.error.saving.message2"), cx.getStatus()); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + MessageDialog.openError(shell, CEditorMessages.getString("CEditor.error.saving.title3"), CEditorMessages.getString("CEditor.error.saving.message3") + t.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + } finally { + + if (progressMonitor != null) + progressMonitor.setCanceled(!success); + } + } + + /** + * Gets the outline page of the c-editor + */ + public CContentOutlinePage getOutlinePage() { + if (fOutlinePage == null) { + fOutlinePage= new CContentOutlinePage(this); + fOutlinePage.addSelectionChangedListener(this); + } + return fOutlinePage; + } + + /** + * @see AbstractTextEditor#getAdapter(Class) + */ + public Object getAdapter(Class required) { + if (IContentOutlinePage.class.equals(required)) { + return getOutlinePage(); + } + return super.getAdapter(required); + } + /** + * Handles a property change event describing a change + * of the editor's preference store and updates the preference + * related editor properties. + * + * @param event the property change event + */ + protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { + AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); + + try { + if(asv != null) { + + String property= event.getProperty(); + if (PREFERENCE_COLOR_FOREGROUND.equals(property) || PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT.equals(property) || + PREFERENCE_COLOR_BACKGROUND.equals(property) || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)) + { + initializeViewerColors(getSourceViewer()); + getSourceViewer().getTextWidget().redraw(); + return; + } + + if (CURRENT_LINE.equals(property)) { + if (isLineHighlightingEnabled()) + startLineHighlighting(); + else + stopLineHighlighting(); + return; + } + + if (CURRENT_LINE_COLOR.equals(property)) { + if (fLinePainter != null) + fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR)); + return; + } + + if (PROBLEM_INDICATION.equals(property)) { + if (isProblemIndicationEnabled()) + startProblemIndication(); + else + stopProblemIndication(); + return; + } + + if (PROBLEM_INDICATION_COLOR.equals(property)) { + if (fProblemPainter != null) + fProblemPainter.setHighlightColor(getColor(PROBLEM_INDICATION_COLOR)); + return; + } + + if (PRINT_MARGIN.equals(property)) { + if (isShowingPrintMarginEnabled()) + startShowingPrintMargin(); + else + stopShowingPrintMargin(); + return; + } + + if (PRINT_MARGIN_COLOR.equals(property)) { + if (fPrintMarginPainter != null) + fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR)); + return; + } + + if (PRINT_MARGIN_COLUMN.equals(property)) { + if (fPrintMarginPainter != null) + fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN)); + return; + } + + if (CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) { + SourceViewerConfiguration configuration= getSourceViewerConfiguration(); + String[] types= configuration.getConfiguredContentTypes(asv); + for (int i= 0; i < types.length; i++) + asv.setIndentPrefixes(configuration.getIndentPrefixes(asv, types[i]), types[i]); + + if (fTabConverter != null) + fTabConverter.setNumberOfSpacesPerTab(getPreferenceStore().getInt(CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH)); + + Object value= event.getNewValue(); + + if (value instanceof Integer) { + asv.getTextWidget().setTabs(((Integer) value).intValue()); + + } else if (value instanceof String) { + asv.getTextWidget().setTabs(Integer.parseInt((String) value)); + } + } + + if (SPACES_FOR_TABS.equals(property)) { + if (isTabConversionEnabled()) + startTabConversion(); + else + stopTabConversion(); + return; + } + + if (MATCHING_BRACKETS.equals(property)) { + if (isBracketHighlightingEnabled()) + startBracketHighlighting(); + else + stopBracketHighlighting(); + return; + } + + if (MATCHING_BRACKETS_COLOR.equals(property)) { + if (fBracketPainter != null) + fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR)); + return; + } + if (MATCHING_BRACKETS_NOBOX.equals(property)) { + if (isBracketHighlightingEnabled()) + setBracketHighlightingStyle(); + return; + } + } + } finally { + + super.handlePreferenceStoreChanged(event); + + if (asv != null && affectsTextPresentation(event)) + asv.invalidateTextPresentation(); + } + } + + /** + * Initializes the given viewer's colors. + * + * @param viewer the viewer to be initialized + */ + private void initializeViewerColors(ISourceViewer viewer) { + + IPreferenceStore store= getPreferenceStore(); + if (store != null) { + + StyledText styledText= viewer.getTextWidget(); + + // ----------- foreground color -------------------- + Color color= store.getBoolean(PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT) + ? null + : createColor(store, PREFERENCE_COLOR_FOREGROUND, styledText.getDisplay()); + styledText.setForeground(color); + + if (fForegroundColor != null) + fForegroundColor.dispose(); + + fForegroundColor= color; + + // ---------- background color ---------------------- + color= store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT) + ? null + : createColor(store, PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay()); + styledText.setBackground(color); + + if (fBackgroundColor != null) + fBackgroundColor.dispose(); + + fBackgroundColor= color; + } + } + + /** + * Creates a color from the information stored in the given preference store. + * Returns null if there is no such information available. + */ + private Color createColor(IPreferenceStore store, String key, Display display) { + + RGB rgb= null; + + if (store.contains(key)) { + + if (store.isDefault(key)) + rgb= PreferenceConverter.getDefaultColor(store, key); + else + rgb= PreferenceConverter.getColor(store, key); + + if (rgb != null) + return new Color(display, rgb); + } + + return null; + } + + /** + * @see ISelectionChangedListener#selectionChanged + */ + public void selectionChanged(SelectionChangedEvent event) { + ISelection sel= event.getSelection(); + if (sel instanceof IStructuredSelection) { + IStructuredSelection selection= (IStructuredSelection)sel; + Object obj= selection.getFirstElement(); + if (obj instanceof ISourceReference) { + try { + ISourceRange range = ((ISourceReference)obj).getSourceRange(); + if (range != null) { + setSelection(range, !isActivePart()); + } + } catch (CModelException e) { + } + } + } + } + + private void setSelection(ISourceRange element, boolean moveCursor) { + if (element != null) { + try { + int start= element.getStartPos(); + int length= element.getLength(); + setHighlightRange(start, length, moveCursor); + + if (moveCursor) { + start= element.getIdStartPos(); + if (start > -1) { + length= element.getIdLength(); + if (getSourceViewer() != null) { + getSourceViewer().revealRange(start, length); + getSourceViewer().setSelectedRange(start, length); + } + } + updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + } + return; + + } catch (IllegalArgumentException x) { + } + } + + if (moveCursor) + resetHighlightRange(); + } + + private boolean isActivePart() { + IWorkbenchWindow window= getSite().getWorkbenchWindow(); + IPartService service= window.getPartService(); + return (this == service.getActivePart()); + } + + public void dispose() { + + stopBracketHighlighting(); + stopLineHighlighting(); + + if (fPaintManager != null) { + fPaintManager.dispose(); + fPaintManager= null; + } + if (fCEditorErrorTickUpdater != null) { + fCEditorErrorTickUpdater.setAnnotationModel(null); + fCEditorErrorTickUpdater= null; + } + + super.dispose(); + } + + protected void createActions() + { + super.createActions(); + + fEditorActions = getContextMenuActions(); + + for ( int i = 0; i < fEditorActions.length; ++i ) + setAction( fEditorActions[i].getId(), fEditorActions[i] ); + + // Default text editing menu items + setAction("Comment", new TextOperationAction(CEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX)); //$NON-NLS-1$ //$NON-NLS-2$ + setAction("Uncomment", new TextOperationAction(CEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX)); //$NON-NLS-1$ //$NON-NLS-2$ + setAction("Format", new TextOperationAction(CEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT)); //$NON-NLS-1$ //$NON-NLS-2$ + setAction("ContentAssistProposal", new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistProposal.", this, ISourceViewer.CONTENTASSIST_PROPOSALS)); //$NON-NLS + + setAction("AddIncludeOnSelection", new AddIncludeOnSelectionAction(this)); //$NON-NLS-1$ + setAction("OpenOnSelection", new OpenOnSelectionAction(this)); + //setAction("OrganizeImports", new OrganizeImportsAction(this)); //$NON-NLS-1$ + + + fSearchForReferencesAction= new SearchForReferencesAction(getSelectionProvider()); + + fRulerSingleclickAction = new CRulerSingleclickAction( getVerticalRuler(), this, getSourceViewer()); + + fRulerActions = getRulerActions(); + + for ( int i = 0; i < fRulerActions.length; ++i ) + { + setAction( fRulerActions[i].getId(), fRulerActions[i] ); + + /* To make it configurable, we could do + if(fRulerActions[i].isDefaultDoubleClick()) { + setAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK, fRulerActions[i]); + } + */ + } + + /* + * Create the action for the single-click in the ruler + */ + setAction( fRulerSingleclickAction.getId(), fRulerSingleclickAction ); + + /* + * Instead, take action 0 as the double-click default + */ + + if ( fRulerActions.length > 0 ) + { + setAction( ITextEditorActionConstants.RULER_DOUBLE_CLICK, fRulerActions[0] ); + } + } + + public void editorContextMenuAboutToShow( IMenuManager menu ) + { + super.editorContextMenuAboutToShow( menu ); + + addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_REORGANIZE); + addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_GENERATE); + addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_NEW); + + for ( int i = 0; i < fEditorActions.length; ++i ) + { + if ( fEditorActions[i].isEnabled() ) + { + String menuPath = fEditorActions[i].getMenuPath(); + addAction( menu, + ( menuPath != null ) ? menuPath : ITextEditorActionConstants.GROUP_REST, + fEditorActions[i].getId() ); + } + } + + // Code formatting menu items -- only show in C perspective + addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Comment"); //$NON-NLS-1$ + addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Uncomment"); //$NON-NLS-1$ + // @@@ disabled for now until we get it to do something... + //addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$ + + MenuManager search= new MenuManager("Search", IContextMenuConstants.GROUP_SEARCH); //$NON-NLS-1$ + menu.appendToGroup(ITextEditorActionConstants.GROUP_FIND, search); + if(fSearchForReferencesAction.canActionBeAdded(getSelectionProvider().getSelection())) { + search.add(fSearchForReferencesAction); + } + + addAction(menu, IContextMenuConstants.GROUP_GENERATE, "ContentAssistProposal"); //$NON-NLS-1$ + addAction(menu, IContextMenuConstants.GROUP_GENERATE, "AddIncludeOnSelection"); //$NON-NLS-1$ + addAction(menu, IContextMenuConstants.GROUP_GENERATE, "OpenOnSelection"); //$NON-NLS-1$ + } + + + /* + * Add our items to the ruler menu. Since most people care about breakpoints + * and not about tasks, we add our items before the default task ones. + */ + protected void rulerContextMenuAboutToShow( IMenuManager menu ) + { + + for ( int i = 0; i < fRulerActions.length; ++i ) + { + if ( fRulerActions[i].isEnabled() ) + addAction( menu, fRulerActions[i].getId() ); + } + + /* Give us a nice separator */ + menu.add(new Separator(ITextEditorActionConstants.GROUP_REST)); + + super.rulerContextMenuAboutToShow( menu ); + } + + + /** + * Internal interface for a cursor listener. I.e. aggregation + * of mouse and key listener. + */ + interface ICursorListener extends MouseListener, KeyListener { + }; + + /** + * The AbstractTextEditor implementation of this + * IWorkbenchPart method creates the vertical ruler and + * source viewer. Subclasses may extend. + * + * We attach our own mouseDown listener on the menu bar, + * and our own listener for cursor/key/selection events to update cursor position in + * status bar. + */ + public void createPartControl(Composite parent) { + super.createPartControl(parent); + fPaintManager= new PaintManager(getSourceViewer()); + Control ruler; + ruler = getVerticalRuler().getControl(); + MouseListener mListener = new MouseListener() { + public void mouseDown(MouseEvent e) { + if(e.button == 1) { + IAction action= getAction(fRulerSingleclickAction.getId()); + if (action != null) { + action.run(); + } + } + } + + public void mouseUp(MouseEvent e) {} + + public void mouseDoubleClick(MouseEvent e) {} + }; + ruler.addMouseListener(mListener); + + ISelectionChangedListener sListener = new ISelectionChangedListener() { + private Runnable fRunnable= new Runnable() { + public void run() { + updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + } + }; + + private Display fDisplay; + + public void selectionChanged(SelectionChangedEvent event) { + if (fDisplay == null) + fDisplay= getSite().getShell().getDisplay(); + fDisplay.asyncExec(fRunnable); + } + }; + + getSelectionProvider().addSelectionChangedListener(sListener); + + ICursorListener fCursorListener = new ICursorListener() { + public void keyPressed(KeyEvent e) { + if (e.keyCode != 0) { + StyledText styledText= (StyledText) e.widget; + int action = styledText.getKeyBinding(e.keyCode | e.stateMask); + if (ST.TOGGLE_OVERWRITE == action) { + fInserting= !fInserting; + updateStatusField(CTextEditorActionConstants.STATUS_INPUT_MODE); + } else { //if(action == ST.LINE_UP || action == ST.LINE_DOWN || action == ST.COLUMN_NEXT || action == ST.COLUMN_PREVIOUS) { + updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + } + } + } + + public void keyReleased(KeyEvent e) { + updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + } + + public void mouseDoubleClick(MouseEvent e) { + } + + public void mouseDown(MouseEvent e) { + } + + public void mouseUp(MouseEvent e) { + updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + } + }; + + StyledText styledText= getSourceViewer().getTextWidget(); + styledText.addMouseListener(fCursorListener); + styledText.addKeyListener(fCursorListener); + + initializeViewerColors(getSourceViewer()); + + if (isLineHighlightingEnabled()) + startLineHighlighting(); + if (isProblemIndicationEnabled()) + startProblemIndication(); + if (isShowingPrintMarginEnabled()) + startShowingPrintMargin(); + if (isTabConversionEnabled()) + startTabConversion(); + if (isBracketHighlightingEnabled()) + startBracketHighlighting(); + + + } + + /* + * @see ITextEditorExtension#setStatusField(IStatusField, String) + */ + public void setStatusField(IStatusField field, String category) { + //Assert.isNotNull(category); + if (field != null) { + + if (fStatusFields == null) + fStatusFields= new HashMap(3); + + fStatusFields.put(category, field); + updateStatusField(category); + + } else if (fStatusFields != null) + fStatusFields.remove(category); + } + + + /** + * Updates the status fields for the given category. + * + * @param category + */ + protected void updateStatusField(String category) { + if (CTextEditorActionConstants.STATUS_CURSOR_POS.equals(category)) { + + IStatusField field= getStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS); + if (field != null) + field.setText(getCursorPosition()); + + } else if (CTextEditorActionConstants.STATUS_INPUT_MODE.equals(category)) { + + IStatusField field= getStatusField(CTextEditorActionConstants.STATUS_INPUT_MODE); + if (field != null) + field.setText(isInInsertMode() ? "Insert" : "Overwrite"); + } + } + + /** + * Returns whether this editor is in overwrite or insert mode. + * + * @return true if in insert mode, + * false for overwrite mode + */ + protected boolean isInInsertMode() { + return fInserting; + } + + + + /** + * Returns a description of the cursor position. + * + * @return a description of the cursor position + */ + protected String getCursorPosition() { + ISourceViewer viewer = getSourceViewer(); + if(viewer == null) + return ""; + StyledText styledText= viewer.getTextWidget(); + + int offset= viewer.getVisibleRegion().getOffset(); + int caret= offset + styledText.getCaretOffset(); + IDocument document= viewer.getDocument(); + + try { + + int line=document.getLineOfOffset(caret); + + int lineOffset= document.getLineOffset(line); + int occurrences= 0; + for (int i= lineOffset; i < caret; i++) + if ('\t' == document.getChar(i)) + ++ occurrences; + + int tabWidth= styledText.getTabs(); + int column= caret - lineOffset + (tabWidth -1) * occurrences; + + return ((line + 1) + " : " + (column + 1)); + + } catch (BadLocationException x) { + return "??"; + } + } + + private Color getColor(String key) { + RGB rgb= PreferenceConverter.getColor(getPreferenceStore(), key); + return getColor(rgb); + } + + private Color getColor(RGB rgb) { + CTextTools textTools= CPlugin.getDefault().getTextTools(); + return textTools.getColorManager().getColor(rgb); + } + + private IMarker getNextError(int offset, boolean forward) { + + IMarker nextError= null; + + IDocument document= getDocumentProvider().getDocument(getEditorInput()); + int endOfDocument= document.getLength(); + int distance= 0; + + IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput()); + Iterator e= model.getAnnotationIterator(); + while (e.hasNext()) { + Annotation a= (Annotation) e.next(); + if (a instanceof CMarkerAnnotation) { + MarkerAnnotation ma= (MarkerAnnotation) a; + IMarker marker= ma.getMarker(); + + if (MarkerUtilities.isMarkerType(marker, IMarker.PROBLEM)) { + Position p= model.getPosition(a); + if (!p.includes(offset)) { + + int currentDistance= 0; + + if (forward) { + currentDistance= p.getOffset() - offset; + if (currentDistance < 0) + currentDistance= endOfDocument - offset + p.getOffset(); + } else { + currentDistance= offset - p.getOffset(); + if (currentDistance < 0) + currentDistance= offset + endOfDocument - p.getOffset(); + } + + if (nextError == null || (currentDistance < distance && currentDistance != 0)) { + distance= currentDistance; + if(distance == 0) distance = endOfDocument; + nextError= marker; + } + + + } + } + + } + } + + return nextError; + } + + public void gotoError(boolean forward) { + + ISelectionProvider provider= getSelectionProvider(); + + if (fStatusLineClearer != null) { + provider.removeSelectionChangedListener(fStatusLineClearer); + fStatusLineClearer= null; + } + + ITextSelection s= (ITextSelection) provider.getSelection(); + IMarker nextError= getNextError(s.getOffset(), forward); + + if (nextError != null) { + + gotoMarker(nextError); + + IWorkbenchPage page= getSite().getPage(); + + IViewPart view= view= page.findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$ + if (view instanceof TaskList) { + StructuredSelection ss= new StructuredSelection(nextError); + ((TaskList) view).setSelection(ss, true); + } + + getStatusLineManager().setErrorMessage(nextError.getAttribute(IMarker.MESSAGE, "")); //$NON-NLS-1$ + fStatusLineClearer= new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + getSelectionProvider().removeSelectionChangedListener(fStatusLineClearer); + fStatusLineClearer= null; + getStatusLineManager().setErrorMessage(""); //$NON-NLS-1$ + } + }; + provider.addSelectionChangedListener(fStatusLineClearer); + + } else { + + getStatusLineManager().setErrorMessage(""); //$NON-NLS-1$ + + } + } + /* + * Get the dektop's StatusLineManager + */ + protected IStatusLineManager getStatusLineManager() { + IEditorActionBarContributor contributor= getEditorSite().getActionBarContributor(); + if (contributor instanceof EditorActionBarContributor) { + return ((EditorActionBarContributor) contributor).getActionBars().getStatusLineManager(); + } + return null; + } + + /** + * LIneHighlighting manager + */ + private void startLineHighlighting() { + if (fLinePainter == null) { + ISourceViewer sourceViewer= getSourceViewer(); + fLinePainter= new LinePainter(sourceViewer); + fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR)); + fPaintManager.addPainter(fLinePainter); + } + } + + private void stopLineHighlighting() { + if (fLinePainter != null) { + fPaintManager.removePainter(fLinePainter); + fLinePainter.deactivate(true); + fLinePainter.dispose(); + fLinePainter= null; + } + } + + private boolean isLineHighlightingEnabled() { + IPreferenceStore store= getPreferenceStore(); + return store.getBoolean(CURRENT_LINE); + } + + private void startProblemIndication() { + if (fProblemPainter == null) { + fProblemPainter= new ProblemPainter(this, getSourceViewer()); + fProblemPainter.setHighlightColor(getColor(PROBLEM_INDICATION_COLOR)); + fPaintManager.addPainter(fProblemPainter); + } + } + + private void stopProblemIndication() { + if (fProblemPainter != null) { + fPaintManager.removePainter(fProblemPainter); + fProblemPainter.deactivate(true); + fProblemPainter.dispose(); + fProblemPainter= null; + } + } + + private boolean isProblemIndicationEnabled() { + IPreferenceStore store= getPreferenceStore(); + return store.getBoolean(PROBLEM_INDICATION); + } + + private void startShowingPrintMargin() { + if (fPrintMarginPainter == null) { + fPrintMarginPainter= new PrintMarginPainter(getSourceViewer()); + fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR)); + fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN)); + fPaintManager.addPainter(fPrintMarginPainter); + } + } + + private void stopShowingPrintMargin() { + if (fPrintMarginPainter != null) { + fPaintManager.removePainter(fPrintMarginPainter); + fPrintMarginPainter.deactivate(true); + fPrintMarginPainter.dispose(); + fPrintMarginPainter= null; + } + } + + private boolean isShowingPrintMarginEnabled() { + IPreferenceStore store= getPreferenceStore(); + return store.getBoolean(PRINT_MARGIN); + } + + private void startTabConversion() { + if (fTabConverter == null) { + fTabConverter= new TabConverter(); + fTabConverter.setNumberOfSpacesPerTab(getPreferenceStore().getInt(CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH)); + AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); + asv.addTextConverter(fTabConverter); + } + } + + private void stopTabConversion() { + if (fTabConverter != null) { + AdaptedSourceViewer asv= (AdaptedSourceViewer) getSourceViewer(); + asv.removeTextConverter(fTabConverter); + fTabConverter= null; + } + } + + private boolean isTabConversionEnabled() { + IPreferenceStore store= getPreferenceStore(); + return store.getBoolean(SPACES_FOR_TABS); + } + + private void startBracketHighlighting() { + if (fBracketPainter == null) { + ISourceViewer sourceViewer= getSourceViewer(); + fBracketPainter= new BracketPainter(sourceViewer); + fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR)); + fPaintManager.addPainter(fBracketPainter); + IPreferenceStore store= getPreferenceStore(); + fBracketPainter.setHighlightStyle(store.getBoolean(MATCHING_BRACKETS_NOBOX)); + } + } + + private void stopBracketHighlighting() { + if (fBracketPainter != null) { + fPaintManager.removePainter(fBracketPainter); + fBracketPainter.deactivate(true); + fBracketPainter.dispose(); + fBracketPainter= null; + } + } + + private boolean isBracketHighlightingEnabled() { + IPreferenceStore store= getPreferenceStore(); + return store.getBoolean(MATCHING_BRACKETS); + } + + private void setBracketHighlightingStyle() { + IPreferenceStore store= getPreferenceStore(); + if(fBracketPainter != null) { + fBracketPainter.setHighlightStyle(store.getBoolean(MATCHING_BRACKETS_NOBOX)); + } + } + + interface ITextConverter { + void customizeDocumentCommand(IDocument document, DocumentCommand command); + }; + + static class TabConverter implements ITextConverter { + + private String fTabString= ""; + + public void setNumberOfSpacesPerTab(int ratio) { + StringBuffer buffer= new StringBuffer(); + for (int i= 0; i < ratio; i++) + buffer.append(' '); + fTabString= buffer.toString(); + } + + public void customizeDocumentCommand(IDocument document, DocumentCommand command) { + String text= command.text; + if (text != null) { + int index= text.indexOf('\t'); + if (index > -1) { + int length= text.length(); + StringBuffer buffer= new StringBuffer(); + buffer.append(text.substring(0, index)); + for (int i= index; i < length; i++) { + char c= text.charAt(i); + if (c == '\t') + buffer.append(fTabString); + else + buffer.append(c); + } + command.text= buffer.toString(); + } + } + } + }; + + /* Source code language to display */ + public final static String LANGUAGE_CPP= "CEditor.language.cpp"; + public final static String LANGUAGE_C= "CEditor.language.c"; + + /** + * Adapted source viewer for CEditor + */ + + public class AdaptedSourceViewer extends SourceViewer implements ITextViewerExtension { + + private List fTextConverters; + private String fDisplayLanguage; + //private OverviewRuler fOverviewRuler; + //private boolean fIsOverviewRulerVisible; + + //private IVerticalRuler fCachedVerticalRuler; + //private boolean fCachedIsVerticalRulerVisible; + + + public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int styles, String language) { + super(parent, ruler, styles); + + fDisplayLanguage = language; + //fCachedVerticalRuler= ruler; + //fCachedIsVerticalRulerVisible= (ruler != null); + //fOverviewRuler= new OverviewRuler(VERTICAL_RULER_WIDTH); + + //delayedCreateControl(parent, styles); + } + + /* + * @see ISourceViewer#showAnnotations(boolean) + * + public void showAnnotations(boolean show) { + fCachedIsVerticalRulerVisible= (show && fCachedVerticalRuler != null); + super.showAnnotations(show); + } */ + /* + public IContentAssistant getContentAssistant() { + return fContentAssistant; + } */ + + /* + * @see ITextOperationTarget#doOperation(int) + */ + public void doOperation(int operation) { + + if (getTextWidget() == null) { + return; + } + + super.doOperation(operation); + } + + /* + * @see ITextOperationTarget#canDoOperation(int) + * + public boolean canDoOperation(int operation) { + + if (getTextWidget() == null) + return false; + + switch (operation) { + case SHIFT_RIGHT: + case SHIFT_LEFT: + return isEditable() && fIndentChars != null && isBlockSelected(); + } + + return super.canDoOperation(operation); + }*/ + + public void insertTextConverter(ITextConverter textConverter, int index) { + throw new UnsupportedOperationException(); + } + + public void addTextConverter(ITextConverter textConverter) { + if (fTextConverters == null) { + fTextConverters= new ArrayList(1); + fTextConverters.add(textConverter); + } else if (!fTextConverters.contains(textConverter)) + fTextConverters.add(textConverter); + } + + public void removeTextConverter(ITextConverter textConverter) { + if (fTextConverters != null) { + fTextConverters.remove(textConverter); + if (fTextConverters.size() == 0) + fTextConverters= null; + } + } + + /* + * @see TextViewer#customizeDocumentCommand(DocumentCommand) + */ + protected void customizeDocumentCommand(DocumentCommand command) { + super.customizeDocumentCommand(command); + if (fTextConverters != null) { + for (Iterator e = fTextConverters.iterator(); e.hasNext();) + ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(), command); + } + } + + /* + public IVerticalRuler getVerticalRuler() { + return fCachedVerticalRuler; + } + + public boolean isVerticalRulerVisible() { + return fCachedIsVerticalRulerVisible; + } + + public OverviewRuler getOverviewRuler() { + return fOverviewRuler; + } + + /* + * @see TextViewer#createControl(Composite, int) + * + protected void createControl(Composite parent, int styles) { + // do nothing here + } + + protected void delayedCreateControl(Composite parent, int styles) { + //create the viewer + super.createControl(parent, styles); + + Control control= getControl(); + if (control instanceof Composite) { + Composite composite= (Composite) control; + composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this)); + fOverviewRuler.createControl(composite, this); + } + } + + public void hideOverviewRuler() { + fIsOverviewRulerVisible= false; + Control control= getControl(); + if (control instanceof Composite) { + Composite composite= (Composite) control; + composite.layout(); + } + } + + public void showOverviewRuler() { + fIsOverviewRulerVisible= true; + Control control= getControl(); + if (control instanceof Composite) { + Composite composite= (Composite) control; + composite.layout(); + } + } + + public boolean isOverviewRulerVisible() { + return fIsOverviewRulerVisible; + } */ + + /* + * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int) + * + public void setDocument(IDocument document, IAnnotationModel annotationModel, int visibleRegionOffset, int visibleRegionLength) { + super.setDocument(document, annotationModel, visibleRegionOffset, visibleRegionLength); + fOverviewRuler.setModel(annotationModel); + } */ + + /** + * Invalidates the current presentation by sending an initialization + * event to all text listener. + */ +/* + public final void invalidateTextPresentation() { + IDocument doc = getDocument(); + if(doc != null) { + fireInputDocumentChanged(doc, doc); + } + } +*/ + public void setDisplayLanguage(String language) { + fDisplayLanguage = language; + } + + public String getDisplayLanguage() { + return fDisplayLanguage; + } + /** + * Internal verify listener. + */ + class TextVerifyListener implements VerifyListener { + + private boolean fForward= true; + + /** + * Tells the listener to forward received events. + */ + public void forward(boolean forward) { + fForward= forward; + } + + /* + * @see VerifyListener#verifyText(VerifyEvent) + */ + public void verifyText(VerifyEvent e) { + if (fForward) + handleVerifyEvent(e); + } + }; + + /** + * The viewer's manager of registered verify key listeners. + * Uses batches rather than robust iterators because of + * performance issues. + */ + class VerifyKeyListenersManager implements VerifyKeyListener { + + class Batch { + int index; + VerifyKeyListener listener; + + public Batch(VerifyKeyListener l, int i) { + listener= l; + index= i; + } + }; + + private List fListeners= new ArrayList(); + private List fBatched= new ArrayList(); + private Iterator fIterator; + + /* + * @see VerifyKeyListener#verifyKey(VerifyEvent) + */ + public void verifyKey(VerifyEvent event) { + if (fListeners.isEmpty()) + return; + + fIterator= fListeners.iterator(); + while (fIterator.hasNext() && event.doit) { + VerifyKeyListener listener= (VerifyKeyListener) fIterator.next(); + listener.verifyKey(event); + } + fIterator= null; + + processBatchedRequests(); + } + + private void processBatchedRequests() { + if (!fBatched.isEmpty()) { + Iterator e= fBatched.iterator(); + while (e.hasNext()) { + Batch batch= (Batch) e.next(); + insertListener(batch.listener, batch.index); + } + fBatched.clear(); + } + } + + /** + * Returns the number of registered verify key listeners. + */ + public int numberOfListeners() { + return fListeners.size(); + } + + /** + * Inserts the given listener at the given index or moves it + * to that index. + * + * @param listener the listener to be inserted + * @param index the index of the listener or -1 for remove + */ + public void insertListener(VerifyKeyListener listener, int index) { + + if (index == -1) { + removeListener(listener); + } else if (listener != null) { + + if (fIterator != null) { + + fBatched.add(new Batch(listener, index)); + + } else { + + int idx= fListeners.indexOf(listener); + if (idx != index) { + + if (idx != -1) + fListeners.remove(idx); + + if (index > fListeners.size()) + fListeners.add(listener); + else + fListeners.add(index, listener); + } + + if (fListeners.size() == 1) + install(); + } + } + } + + /** + * Removes the given listener. + * + * @param listener the listener to be removed + */ + public void removeListener(VerifyKeyListener listener) { + if (listener == null) + return; + + if (fIterator != null) { + + fBatched.add(new Batch(listener, -1)); + + } else { + + fListeners.remove(listener); + if (fListeners.isEmpty()) + uninstall(); + + } + } + + /** + * Installs this manager. + */ + private void install() { + getTextWidget().addVerifyKeyListener(this); + } + + /** + * Uninstalls this manager. + */ + private void uninstall() { + getTextWidget().removeVerifyKeyListener(this); + } + }; + + /** The viewer's manager of verify key listeners */ + private VerifyKeyListenersManager fVerifyKeyListenersManager= new VerifyKeyListenersManager(); + + /* + * @see ITextViewerExtension#appendVerifyKeyListener(VerifyKeyListener) + */ + public void appendVerifyKeyListener(VerifyKeyListener listener) { + int index= fVerifyKeyListenersManager.numberOfListeners(); + fVerifyKeyListenersManager.insertListener(listener, index); + } + + /* + * @see ITextViewerExtension#prependVerifyKeyListener(VerifyKeyListener) + */ + public void prependVerifyKeyListener(VerifyKeyListener listener) { + fVerifyKeyListenersManager.insertListener(listener, 0); + + } + + /* + * @see ITextViewerExtension#removeVerifyKeyListener(VerifyKeyListener) + */ + public void removeVerifyKeyListener(VerifyKeyListener listener) { + fVerifyKeyListenersManager.removeListener(listener); + } + + }; + + + /* + * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int) + */ + protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + // Figure out if this is a C or C++ source file + String filename = getEditorInput().getName(); + boolean c_file = false; + c_file |= filename.endsWith(".c"); + c_file |= filename.endsWith(".h"); + + return new AdaptedSourceViewer(parent, ruler, styles, c_file ? LANGUAGE_C : LANGUAGE_CPP); + } + + /* + * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent) + * Pulled in from 2.0 + */ + protected boolean affectsTextPresentation(PropertyChangeEvent event) { + String p= event.getProperty(); + + boolean affects=MATCHING_BRACKETS_COLOR.equals(p) || + CURRENT_LINE_COLOR.equals(p) || + PROBLEM_INDICATION_COLOR.equals(p); + CTextTools textTools= CPlugin.getDefault().getTextTools(); + affects |= textTools.affectsBehavior(event); + + return affects; // ? affects : super.affectsTextPresentation(event); + } + + private ICEditorContextMenuAction[] getContextMenuActions() + { + LinkedList menuActions = new LinkedList(); + IPluginRegistry pluginRegistry = Platform.getPluginRegistry(); + IExtensionPoint point = pluginRegistry.getExtensionPoint( CPlugin.getDefault().getDescriptor().getUniqueIdentifier(), + ICDTConstants.EP_EDITOR_ACTIONS ); + if ( point != null ) + { + IExtension[] extensions = point.getExtensions(); + for ( int i = 0; i < extensions.length; i++ ) + { + IExtension currentExtension = extensions[i]; + IConfigurationElement[] configElements = currentExtension.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j++ ) + { + IConfigurationElement element = configElements[j]; + if ( element.getName().equals( ICDTConstants.TAG_ACTION ) ) + { + ICEditorContextMenuAction action = null; + try + { + action = (ICEditorContextMenuAction)element.createExecutableExtension( ICDTConstants.ATT_CLASS ); + } + catch( CoreException e ) + { + CPlugin.getDefault().getLog().log( e.getStatus() ); +// ErrorDialog.openError( CPlugin.getDefault().getActiveWorkbenchShell(), null, null, e.getStatus() ); + } + if ( action != null ) + { + action.init( this ); + menuActions.add( action ); + } + } + } + } + } + return (ICEditorContextMenuAction[])menuActions.toArray( new ICEditorContextMenuAction[0] ); + } + + private ICEditorRulerAction[] getRulerActions() + { + LinkedList rulerActions = new LinkedList(); + IPluginRegistry pluginRegistry = Platform.getPluginRegistry(); + IExtensionPoint point = pluginRegistry.getExtensionPoint( CPlugin.getDefault().getDescriptor().getUniqueIdentifier(), + ICDTConstants.EP_EDITOR_RULER_ACTIONS ); + if ( point != null ) + { + IExtension[] extensions = point.getExtensions(); + for ( int i = 0; i < extensions.length; i++ ) + { + IExtension currentExtension = extensions[i]; + IConfigurationElement[] configElements = currentExtension.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j++ ) + { + IConfigurationElement element = configElements[j]; + if ( element.getName().equals( ICDTConstants.TAG_ACTION ) ) + { + ICEditorRulerAction action = null; + try + { + action = (ICEditorRulerAction)element.createExecutableExtension( ICDTConstants.ATT_CLASS ); + } + catch( CoreException e ) + { + CPlugin.getDefault().getLog().log( e.getStatus() ); +// ErrorDialog.openError( CPlugin.getDefault().getActiveWorkbenchShell(), null, null, e.getStatus() ); + } + if ( action != null ) + { + action.init( getVerticalRuler(), this ); + rulerActions.add( action ); + } + } + } + } + } + return (ICEditorRulerAction[])rulerActions.toArray( new ICEditorRulerAction[0] ); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java new file mode 100644 index 00000000000..0b50a161754 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorActionContributor.java @@ -0,0 +1,218 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.ResourceBundle; + +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.texteditor.BasicTextEditorActionContributor; +import org.eclipse.ui.texteditor.IStatusField; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.RetargetTextEditorAction; +import org.eclipse.ui.texteditor.TextEditorAction; +import org.eclipse.ui.texteditor.TextOperationAction; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.IContextMenuConstants; + + +public class CEditorActionContributor extends BasicTextEditorActionContributor { + + protected static class SelectionAction extends TextEditorAction implements ISelectionChangedListener { + + protected int fOperationCode; + protected ITextOperationTarget fOperationTarget= null; + + + public SelectionAction(String prefix, int operation) { + super(CPlugin.getDefault().getResourceBundle(), prefix, null); + fOperationCode= operation; + setEnabled(false); + } + + /** + * @see TextEditorAction#setEditor(ITextEditor) + */ + public void setEditor(ITextEditor editor) { + if (getTextEditor() != null) { + ISelectionProvider p= getTextEditor().getSelectionProvider(); + if (p != null) p.removeSelectionChangedListener(this); + } + + super.setEditor(editor); + + if (editor != null) { + ISelectionProvider p= editor.getSelectionProvider(); + if (p != null) p.addSelectionChangedListener(this); + fOperationTarget= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class); + } else + fOperationTarget= null; + + selectionChanged(null); + } + + /** + * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); + setEnabled(isEnabled); + } + + /** + * @see Action#run() + */ + public void run() { + if (fOperationCode != -1 && fOperationTarget != null) + fOperationTarget.doOperation(fOperationCode); + } + }; + + + protected CEditor fCEditor; + protected RetargetTextEditorAction fContentAssist; + protected RetargetTextEditorAction fAddInclude; + protected RetargetTextEditorAction fOpenOnSelection; + protected SelectionAction fShiftLeft; + protected SelectionAction fShiftRight; + private TextOperationAction caAction; + //private ToggleTextHoverAction fToggleTextHover; + private GotoErrorAction fPreviousError; + private GotoErrorAction fNextError; + private Map fStatusFields; + + private final static String[] STATUSFIELDS= { + CTextEditorActionConstants.STATUS_INPUT_MODE, + CTextEditorActionConstants.STATUS_CURSOR_POS, + }; + + + public CEditorActionContributor() { + super(); + + ResourceBundle bundle = CEditorMessages.getResourceBundle(); + + + fShiftRight= new SelectionAction("Editor.ShiftRight.", ITextOperationTarget.SHIFT_RIGHT); + fShiftLeft= new SelectionAction("Editor.ShiftLeft.", ITextOperationTarget.SHIFT_LEFT); + + CPluginImages.setImageDescriptors(fShiftRight, CPluginImages.T_LCL, CPluginImages.IMG_MENU_SHIFT_RIGHT); + CPluginImages.setImageDescriptors(fShiftLeft, CPluginImages.T_LCL, CPluginImages.IMG_MENU_SHIFT_LEFT); + + fContentAssist = new RetargetTextEditorAction(bundle, "ContentAssistProposal."); + fAddInclude = new RetargetTextEditorAction(bundle, "AddIncludeOnSelection"); + fOpenOnSelection = new RetargetTextEditorAction(bundle, "OpenOnSelection"); + + //fToggleTextHover= new ToggleTextHoverAction(); + fPreviousError= new GotoErrorAction("Editor.PreviousError.", false); //$NON-NLS-1$ + CPluginImages.setImageDescriptors(fPreviousError, CPluginImages.T_TOOL, CPluginImages.IMG_TOOL_GOTO_PREV_ERROR); + fNextError= new GotoErrorAction("Editor.NextError.", true); //$NON-NLS-1$ + CPluginImages.setImageDescriptors(fNextError, CPluginImages.T_TOOL, CPluginImages.IMG_TOOL_GOTO_NEXT_ERROR); + + fStatusFields= new HashMap(3); + for (int i= 0; i < STATUSFIELDS.length; i++) + fStatusFields.put(STATUSFIELDS[i], new StatusLineContributionItem(STATUSFIELDS[i])); + } + + + + /** + * @see IActionBarContributor#contributeToMenu(MenuManager) + */ + public void contributeToMenu(IMenuManager menu) { + + super.contributeToMenu(menu); + + /* + * Hook in the code assist + */ + + IMenuManager editMenu= menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT); + if (editMenu != null) { + editMenu.add(fShiftRight); + editMenu.add(fShiftLeft); + + editMenu.add(new Separator(IContextMenuConstants.GROUP_OPEN)); + editMenu.add(fNextError); + editMenu.add(fPreviousError); + + editMenu.add(new Separator(IContextMenuConstants.GROUP_GENERATE)); + editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fContentAssist); + editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fAddInclude); + editMenu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, fOpenOnSelection); + } + } + + /** + * @see EditorActionBarContributor#contributeToToolBar(IToolBarManager) + */ + public void contributeToToolBar(IToolBarManager tbm) { + super.contributeToToolBar(tbm); + tbm.add(new Separator()); + //tbm.add(fTogglePresentation); + //tbm.add(fToggleTextHover); + tbm.add(fNextError); + tbm.add(fPreviousError); + } + + /** + * @see IEditorActionBarContributor#setActiveEditor(IEditorPart) + */ + public void setActiveEditor(IEditorPart part) { + + super.setActiveEditor(part); + + ITextEditor textEditor= null; + if (part instanceof ITextEditor) + textEditor= (ITextEditor) part; + + if (part instanceof CEditor) { + for (int i= 0; i < STATUSFIELDS.length; i++) + ((CEditor)part).setStatusField(null, STATUSFIELDS[i]); + } + + fShiftRight.setEditor(textEditor); + fShiftLeft.setEditor(textEditor); + fNextError.setEditor(textEditor); + fPreviousError.setEditor(textEditor); + //caAction.setEditor(textEditor); + //caAction.update(); + fContentAssist.setAction(getAction(textEditor, "ContentAssistProposal")); //$NON-NLS-1$ + fAddInclude.setAction(getAction(textEditor, "AddIncludeOnSelection")); //$NON-NLS-1$ + fOpenOnSelection.setAction(getAction(textEditor, "OpenOnSelection")); //$NON-NLS-1$ + + + if (part instanceof CEditor) { + CEditor ed = (CEditor) part; + for (int i= 0; i < STATUSFIELDS.length; i++) + ed.setStatusField((IStatusField) fStatusFields.get(STATUSFIELDS[i]), STATUSFIELDS[i]); + } + } + + /* + * @see EditorActionBarContributor#contributeToStatusLine(IStatusLineManager) + * + * More code here only until we move to 2.0... + */ + public void contributeToStatusLine(IStatusLineManager statusLineManager) { + super.contributeToStatusLine(statusLineManager); + for (int i= 0; i < STATUSFIELDS.length; i++) + statusLineManager.add((IContributionItem) fStatusFields.get(STATUSFIELDS[i])); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorErrorTickUpdater.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorErrorTickUpdater.java new file mode 100644 index 00000000000..01ab45ef226 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorErrorTickUpdater.java @@ -0,0 +1,98 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.CElementImageProvider; +import org.eclipse.cdt.internal.ui.CElementLabelProvider; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModelListener; +import org.eclipse.jface.util.Assert; + +import org.eclipse.ui.IEditorInput; + +/** + * The JavaEditorErrorTickUpdater will register as a AnnotationModelListener + * on the annotation model of a Java Editor and update the title images when the annotation + * model changed. + */ +public class CEditorErrorTickUpdater implements IAnnotationModelListener { + + private CEditor fCEditor; + private IAnnotationModel fAnnotationModel; + private CElementLabelProvider fLabelProvider; + + public CEditorErrorTickUpdater(CEditor editor) { + fCEditor= editor; + Assert.isNotNull(editor); + } + + /** + * Defines the annotation model to listen to. To be called when the + * annotation model changes. + * @param model The new annotation model or null + * to uninstall. + */ + public void setAnnotationModel(IAnnotationModel model) { + if (fAnnotationModel != null) { + fAnnotationModel.removeAnnotationModelListener(this); + } + + if (model != null) { + if (fLabelProvider == null) { + fLabelProvider= new CElementLabelProvider(0, CElementImageProvider.SMALL_ICONS, CElementLabelProvider.getAdornmentProviders(true, null)); + } + fAnnotationModel=model; + fAnnotationModel.addAnnotationModelListener(this); + modelChanged(fAnnotationModel); + } else { + if (fLabelProvider != null) { + fLabelProvider.dispose(); + } + fLabelProvider= null; + fAnnotationModel= null; + } + } + + /* + * @see IAnnotationModelListener#modelChanged(IAnnotationModel) + */ + public void modelChanged(IAnnotationModel model) { + Image titleImage= fCEditor.getTitleImage(); + if (titleImage == null) { + return; + } + IEditorInput input= fCEditor.getEditorInput(); + if (input != null) { // might run async, tests needed + ICElement celement= (ICElement) input.getAdapter(ICElement.class); + if (fLabelProvider != null && celement != null) { + Image newImage= fLabelProvider.getImage(celement); + if (titleImage != newImage) { + updatedTitleImage(newImage); + } + } + } + } + + private void updatedTitleImage(final Image newImage) { + Shell shell= fCEditor.getEditorSite().getShell(); + if (shell != null && !shell.isDisposed()) { + shell.getDisplay().syncExec(new Runnable() { + public void run() { + fCEditor.updatedTitleImage(newImage); + } + }); + } + } + +} + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java new file mode 100644 index 00000000000..4d858decf7a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java @@ -0,0 +1,43 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + + +public class CEditorMessages +{ + private static final String RESOURCE_BUNDLE = "org.eclipse.cdt.internal.ui.editor.CEditorMessages"; + + + private static ResourceBundle fgResourceBundle = ResourceBundle.getBundle( RESOURCE_BUNDLE ); + + + private CEditorMessages() + { + } + + + public static ResourceBundle getResourceBundle() + { + return fgResourceBundle; + } + + public static String getString( String key ) + { + try + { + return fgResourceBundle.getString( key ); + } + catch( MissingResourceException e ) + { + return "!" + key + "!"; + } + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties new file mode 100644 index 00000000000..970a4a2f325 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties @@ -0,0 +1,139 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +AddIncludeOnSelection.description=Add include statement on selection +AddIncludeOnSelection.dialog.message=&Choose element to generate an include statement for: +AddIncludeOnSelection.dialog.title=Add Include +AddIncludeOnSelection.error.message1=Adding include statements failed +AddIncludeOnSelection.error.message2=Error +AddIncludeOnSelection.error.message3=Error +AddIncludeOnSelection.error.message4=BadLocationException: +AddIncludeOnSelection.label=Add I&nclude@Ctrl+Shift+N +AddIncludeOnSelection.tooltip=Add Include Statement on Selection + +ClassFileEditor.error.invalid_input_message=Invalid input for Class File Editor + +ClassFileMarkerAnnotationModel.error.isAcceptable=ClassFileMarkerAnnotationModel.isAcceptable +ClassFileMarkerAnnotationModel.error.isAffected=ClassFileMarkerAnnotationModel.isAffected +ClassFileMarkerAnnotationModel.error.resourceChanged=ClassFileMarkerAnnotationModel.resourceChanged + +CEditor.error.saving.message1=File has been deleted. +CEditor.error.saving.message2=Could not save file. +CEditor.error.saving.message3=Could not save file. +CEditor.error.saving.title1=Cannot Save +CEditor.error.saving.title2=Save Problems +CEditor.error.saving.title3=Save Problems +CEditorPreferencePage.description= C Editor Preferences + +DeleteISourceManipulations.description=Delete the selected element in the editor +DeleteISourceManipulations.error.deleting.message1=Cannot delete element: +DeleteISourceManipulations.error.deleting.title1=Problems while deleting element +DeleteISourceManipulations.label=&Delete +DeleteISourceManipulations.tooltip=Delete the selected element in the editor + +EditorDisplay.description=Display +EditorDisplay.label=D&isplay +EditorDisplay.tooltip=Display +EditorDisplay.error.title1=Cannot open Display viewer + +JavaOutlinePage.ContextMenu.refactoring.label=&Refactor +JavaOutlinePage.HideFields.description.checked=Shows Fields +JavaOutlinePage.HideFields.description.unchecked=Hides Fields +JavaOutlinePage.HideFields.label=Hide Fields +JavaOutlinePage.HideFields.tooltip.checked=Show Fields +JavaOutlinePage.HideFields.tooltip.unchecked=Hide Fields +JavaOutlinePage.HideNonePublicMembers.description.checked=Shows non-public members +JavaOutlinePage.HideNonePublicMembers.description.unchecked=Hides non-public members +JavaOutlinePage.HideNonePublicMembers.label=Show Public Members Only +JavaOutlinePage.HideNonePublicMembers.tooltip.checked=Show Non-Public Members +JavaOutlinePage.HideNonePublicMembers.tooltip.unchecked=Hide Non-Public Members +JavaOutlinePage.HideStaticMembers.description.checked=Shows static members +JavaOutlinePage.HideStaticMembers.description.unchecked=Hides static members +JavaOutlinePage.HideStaticMembers.label=Hide Static Members +JavaOutlinePage.HideStaticMembers.tooltip.checked=Show Static Members +JavaOutlinePage.HideStaticMembers.tooltip.unchecked=Hide Static Members +JavaOutlinePage.Sort.description.checked=Disable Sorting +JavaOutlinePage.Sort.description.unchecked=Enable Sorting +JavaOutlinePage.Sort.label=Sort +JavaOutlinePage.Sort.tooltip.checked=Do Not Sort +JavaOutlinePage.Sort.tooltip.unchecked=Sort +JavaOutlinePage.error.ChildrenProvider.getChildren.message1=JavaOutlinePage.ChildrenProvider.getChildren +JavaOutlinePage.error.ChildrenProvider.hasChildren.message1=JavaOutlinePage.ChildrenProvider.hasChildren + +OpenHierarchy.description=Show the type hierarchy of the selected element +OpenHierarchy.dialog.message=&Select the type to open: +OpenHierarchy.dialog.title=Open Type Hierarchy +OpenHierarchy.label=Open Type &Hierarchy@F4 +OpenHierarchy.tooltip=Show the type hierarchy of the selected element + +OpenOnSelection.description=Open an editor on the selected element +OpenOnSelection.dialog.message=&Select or enter the element to open: +OpenOnSelection.dialog.title=Open On Selection +OpenOnSelection.label=&Open on Selection@F3 +OpenOnSelection.tooltip=Open an editor on the selected element + +OrganizeImports.description=Evaluate all required imports and replace the current imports +OrganizeImports.error.message2=Syntax errors in compilation unit prevent correct evaluation\nof type references. Fix errors first. +OrganizeImports.error.title1=Organize Imports +OrganizeImports.error.title2=Organize Imports +OrganizeImports.label=Or&ganize Imports@Ctrl+Shift+O +OrganizeImports.ok_label=OK +OrganizeImports.tooltip=Evaluate All Required Imports and Replace the Current Imports + +RunToLine.description=Run to line +RunToLine.error.message1=Unable to process run to line request. +RunToLine.error.title1=Run to Line +RunToLine.label=R&un to Line +RunToLine.tooltip=Run to line + +TogglePresentation.tooltip.checked=Show Complete Source +TogglePresentation.tooltip.unchecked=Show Source of Selected Element Only + +ToggleTextHover.tooltip.checked=Hide Text Hover +ToggleTextHover.tooltip.unchecked=Show Text Hover + +NextError.label=Ne&xt Problem@Ctrl+P +NextError.tooltip=Go to Next Problem +NextError.description=Go to next problem + +PreviousError.label=Previo&us Problem@Ctrl+Shift+P +PreviousError.tooltip=Go to Previous Problem +PreviousError.description=Go to previous problem + +ContentAssistProposal.label=Co&ntent Assist@Ctrl+Space +ContentAssistProposal.tooltip=Content Assist +ContentAssistProposal.description=Content Assist + +RunToLine.label=R&un to Line +RunToLine.description=Run to line +RunToLine.error.title1=Run To Line +RunToLine.error.message1=Unable to process run to line request. + +Comment.label=&Comment +Comment.tooltip=Comment the Selected Lines +Comment.description=Turn the selected lines into Java comments + +Uncomment.label=Uncommen&t +Uncomment.tooltip=Uncomment the Selected Java Comment Lines +Uncomment.description=Uncomment the selected Java comment lines + +Format.label=F&ormat +Format.tooltip=Format the Selected Text +Format.description=Format the selected text + +ShiftRight.label=Sh&ift Right@Ctrl+I +ShiftRight.tooltip=Shift Right +ShiftRight.description=Shift the selected text to the right + +ShiftLeft.label=S&hift Left@Ctrl+Shift+I +ShiftLeft.tooltip=Shift Left +ShiftLeft.description=Shift the selected text to the left + +CompilationUnitDocumentProvider.error.createElementInfo=CompilationUnitDocumentProvider.createElementInfo +CompilationUnitDocumentProvider.out_of_sync.message=Compilation unit buffer and document are out of sync + +JavaEditor.Inspect.description=Inspect the result of evaluating the selected text +JavaEditor.Inspect.label=I&nspect +JavaEditor.Inspect.tooltip=Inspect the Result of Evaluating the Selected Text diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorTextHoverDispatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorTextHoverDispatcher.java new file mode 100644 index 00000000000..41107385cbd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorTextHoverDispatcher.java @@ -0,0 +1,60 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.HashMap; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; + +public class CEditorTextHoverDispatcher implements ITextHover +{ + private IEditorPart fEditor = null; + private HashMap fTextHovers = null; + private DefaultCEditorTextHover fDefaultTextHover = null; + + /** + * Constructor for CEditorTextHover + */ + public CEditorTextHoverDispatcher( IEditorPart editor, HashMap textHovers ) + { + fEditor = editor; + fTextHovers = textHovers; + fDefaultTextHover = new DefaultCEditorTextHover( editor ); + } + + /** + * @see ITextHover#getHoverInfo(ITextViewer, IRegion) + */ + public String getHoverInfo( ITextViewer textViewer, IRegion region ) + { + return getCurrentTextHover().getHoverInfo( textViewer, region ); + } + + /** + * @see ITextHover#getHoverRegion(ITextViewer, int) + */ + public IRegion getHoverRegion( ITextViewer textViewer, int offset ) + { + return getCurrentTextHover().getHoverRegion( textViewer, offset ); + } + + private ITextHover getCurrentTextHover() + { + IWorkbenchPage page = fEditor.getSite().getPage(); + if ( page != null ) + { + Object textHover = fTextHovers.get( page.getPerspective().getId() ); + if ( textHover != null && textHover instanceof ITextHover ) + return (ITextHover)textHover; + } + return fDefaultTextHover; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java new file mode 100644 index 00000000000..8ab0cbcab8a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotation.java @@ -0,0 +1,197 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Map; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.search.ui.SearchUI; +import org.eclipse.ui.texteditor.MarkerAnnotation; +import org.eclipse.ui.texteditor.MarkerUtilities; + +import org.eclipse.cdt.core.model.ICModelMarker; + + +public class CMarkerAnnotation extends MarkerAnnotation implements IProblemAnnotation { + + private boolean fIsProblemMarker; + private IDocument fDocument; + private int error_start = -1; + private int error_length = 0; + private IDebugModelPresentation fPresentation; + + public CMarkerAnnotation(IMarker marker, IDocument document) { + super(marker); + fDocument = document; + if (MarkerUtilities.isMarkerType(getMarker(), ICModelMarker.C_MODEL_PROBLEM_MARKER)) { + fIsProblemMarker = true; + try { + String var = (String) getMarker().getAttribute(ICModelMarker.C_MODEL_MARKER_VARIABLE); + if(var != null && fDocument != null) { + int line = getMarker().getAttribute(IMarker.LOCATION, -1) - 1; + if(line >= 0) { + int position = fDocument.getLineOffset(line); + String text = fDocument.get(position, fDocument.getLineLength(line)); + int start = 0, end, pos; + pos = 0; + while(start != -1) { + start = text.indexOf(var, pos); + if(start >= 0) { + if(Character.isJavaIdentifierStart(text.charAt(start + var.length())) == false) { + break; + } + } + pos += var.length(); + } + //start = text.indexOf(var); + if(start >= 0) { + end = start + var.length(); + // We cannot just update the marker attributes as the workspace resource tree is locked + Map map = marker.getAttributes(); + MarkerUtilities.setCharStart(map, position+start); + MarkerUtilities.setCharEnd(map, position+end); + error_start = position+start; + error_length = end-start; + + //getMarker().setAttribute(IMarker.CHAR_START, position+start); + //getMarker().setAttribute(IMarker.CHAR_END, position+end); + } + } + } + } catch (CoreException e) { + } catch (BadLocationException e) { + } + } + } + + /** + * Initializes the annotation's icon representation and its drawing layer + * based upon the properties of the underlying marker. + */ + protected void initialize() { + try { + IMarker marker= getMarker(); + + if (MarkerUtilities.isMarkerType(marker, SearchUI.SEARCH_MARKER)) { + setLayer(2); + setImage(SearchUI.getSearchMarkerImage()); + fIsProblemMarker= false; + return; + } + else if (MarkerUtilities.isMarkerType(marker, IBreakpoint.LINE_BREAKPOINT_MARKER)) { + if (fPresentation == null) + fPresentation= DebugUITools.newDebugModelPresentation(); + + setLayer(4); + setImage(fPresentation.getImage(marker)); + + fIsProblemMarker= false; + return; + } else if (MarkerUtilities.isMarkerType(getMarker(), ICModelMarker.C_MODEL_PROBLEM_MARKER)) { + fIsProblemMarker = true; + String var = (String) marker.getAttribute(ICModelMarker.C_MODEL_MARKER_VARIABLE); + if(var != null && fDocument != null) { + int line = marker.getAttribute(IMarker.LOCATION, -1); + if(line >= 0 && line == -1) { + try { + int position = fDocument.getLineOffset(line); + System.out.println("offset " + position); + String text = fDocument.get(position, fDocument.getLineLength(line)); + System.out.println("text:" + text); + } catch (BadLocationException e) {} + } + } + } else { + if(marker.isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER)) { //|| getMarker().isSubtypeOf(IMarker.SEVERITY_WARNING)) { + fIsProblemMarker= true; + } + fIsProblemMarker = true; + } + + } catch (CoreException e) { + } + + super.initialize(); + } + + /** + * @see IProblemAnnotation#getMessage() + */ + public String getMessage() { + if (fIsProblemMarker) + return getMarker().getAttribute(IMarker.MESSAGE, ""); + return ""; + } + + /** + * @see IProblemAnnotation#isError() + */ + public boolean isError() { + if (fIsProblemMarker) { + int markerSeverity= getMarker().getAttribute(IMarker.SEVERITY, -1); + return (markerSeverity == IMarker.SEVERITY_ERROR); + } + return false; + } + + /** + * @see IProblemAnnotation#isWarning() + */ + public boolean isWarning() { + if (fIsProblemMarker) { + int markerSeverity= getMarker().getAttribute(IMarker.SEVERITY, -1); + return (markerSeverity == IMarker.SEVERITY_WARNING); + } + return false; + } + + /** + * @see IProblemAnnotation#isTemporaryProblem() + */ + public boolean isTemporaryProblem() { + return false; + } + + /** + * @see IProblemAnnotation#getArguments() + */ + public String[] getArguments() { + String [] s = {"problem", "here"}; + //if (fIsProblemMarker) + // return Util.getProblemArgumentsFromMarker(getMarker().getAttribute(CCorePlugin.C_PROBLEMMARKER)); + return s; + //returnm null; + } + + /** + * @see IProblemAnnotation#getId() + */ + public int getId() { + if (fIsProblemMarker) + return getMarker().getAttribute(ICModelMarker.C_MODEL_PROBLEM_MARKER, -1); + return 0; + } + + /** + * @see IProblemAnnotation#isProblem() + */ + public boolean isProblem() { + return fIsProblemMarker; + } + + public int getErrorStart() { + return error_start; + } + public int getErrorLength() { + return error_length; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotationModel.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotationModel.java new file mode 100644 index 00000000000..e0ccb571247 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CMarkerAnnotationModel.java @@ -0,0 +1,73 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.ui.texteditor.MarkerAnnotation; +import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel; + +public class CMarkerAnnotationModel extends ResourceMarkerAnnotationModel { + + /** + * Constructor for CMarkerAnnotationModel + */ + public CMarkerAnnotationModel(IResource resource) { + super(resource); + } + + /** + * @see AbstractMarkerAnnotationModel#createMarkerAnnotation(IMarker) + */ + protected MarkerAnnotation createMarkerAnnotation(IMarker marker) { + return new CMarkerAnnotation(marker, fDocument); + } + /** + * @see AbstractMarkerAnnotationModel#modifyMarkerAnnotation(IMarker) + */ + protected void modifyMarkerAnnotation(IMarker marker) { + MarkerAnnotation a= getMarkerAnnotation(marker); + if (a == null) { + // It might not have been good enough before, but now it + // is, try adding this marker into the model again. + addMarkerAnnotation(marker); + } + super.modifyMarkerAnnotation(marker); + } + + + /** + * Adds the given annotation to this model. Associates the + * annotation with the given position. If requested, all annotation + * model listeners are informed about this model change. If the annotation + * is already managed by this model nothing happens. + * + * @param annotation the annotation to add + * @param position the associate position + * @param fireModelChange indicates whether to notify all model listeners + */ + protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) { + if (!fAnnotations.containsKey(annotation)) { + + // @@@ This is an unfortunate hack because we cannot override addAnnotationMarker() and if we + // update a marker position, there's no way to update the annotation + if(annotation instanceof CMarkerAnnotation) { + int start = ((CMarkerAnnotation)annotation).getErrorStart(); + if(start != -1 && start != position.getOffset()) { + position.setOffset(start); + position.setLength(((CMarkerAnnotation)annotation).getErrorLength()); + } + } + fAnnotations.put(annotation, position); + addPosition(fDocument, position); + + if (fireModelChanged) + fireModelChanged(); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CRulerSingleclickAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CRulerSingleclickAction.java new file mode 100644 index 00000000000..a89a2399375 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CRulerSingleclickAction.java @@ -0,0 +1,54 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.ui.texteditor.ITextEditor; + +public class CRulerSingleclickAction extends Action +{ + final static private String ACTION_ID = "HighlightLine"; + ITextEditor fEditor; + IVerticalRuler fRuler; + ISourceViewer fViewer; + + /** + * Constructor for CRulerSingleclickAction + */ + public CRulerSingleclickAction(IVerticalRuler ruler, ITextEditor editor, ISourceViewer viewer) { + super(); + fRuler = ruler; + fEditor = editor; + fViewer = viewer; + setEnabled( true ); + setId( ACTION_ID ); + } + + /** + * @see IAction#run() + */ + public void run() { + int line= fRuler.getLineOfLastMouseButtonActivity(); + FileEditorInput editorInput = (FileEditorInput)fEditor.getEditorInput(); + IDocument document = fEditor.getDocumentProvider().getDocument(editorInput); + if((fEditor instanceof AbstractTextEditor) && (fViewer != null)) { + try { + + int start = document.getLineOffset( line ); + int length = document.getLineLength( line ); + fViewer.setSelectedRange(start, length); + } catch (BadLocationException e) {} + } + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CTextEditorActionConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CTextEditorActionConstants.java new file mode 100644 index 00000000000..96121b6af21 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CTextEditorActionConstants.java @@ -0,0 +1,26 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.ui.IWorkbenchActionConstants; + + +public interface CTextEditorActionConstants extends IWorkbenchActionConstants { + /** + * Status category "input position". + */ + static final String STATUS_CURSOR_POS= "CursorPosition"; + + + /** + * Status category "input mode". + */ + static final String STATUS_INPUT_MODE= "InputMode"; + + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultCEditorTextHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultCEditorTextHover.java new file mode 100644 index 00000000000..e029e62290a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultCEditorTextHover.java @@ -0,0 +1,159 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; + +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.core.index.IndexModel; +import org.eclipse.cdt.core.index.TagFlags; +import org.eclipse.cdt.internal.ui.CCompletionContributorManager; +import org.eclipse.cdt.internal.ui.text.CWordFinder; +import org.eclipse.cdt.ui.IFunctionSummary; + +public class DefaultCEditorTextHover implements ITextHover +{ + protected IEditorPart fEditor; + + /** + * Constructor for DefaultCEditorTextHover + */ + public DefaultCEditorTextHover( IEditorPart editor ) + { + fEditor = editor; + } + + /** + * @see ITextHover#getHoverInfo(ITextViewer, IRegion) + */ + public String getHoverInfo( ITextViewer viewer, IRegion region ) + { + String result = null; + String expression = null; + + if(fEditor == null) + return null; + try + { + expression = viewer.getDocument().get( region.getOffset(), region.getLength() ); + expression = expression.trim(); + if ( expression.length() == 0 ) + return null; + + // We are just doing some C, call the Help to get info + + IFunctionSummary fs = CCompletionContributorManager.getFunctionInfo(expression); + if(fs != null) { + StringBuffer s = new StringBuffer(); + s.append(expression + "() - " + fs.getSummary() + "\n\n" + fs.getSynopsis()); + int i; + for(i = 0; i < s.length(); i++) { + if(s.charAt(i) == '\\') { + if((i + 1 < s.length()) && s.charAt(i+1) == 'n') { + s.replace(i, i + 2, "\n"); + } + } + } + i = s.length(); + // Eat the last cariage return for nicer looking text + if(i != 0 && s.charAt(i - 1) == '\n') { + s.replace(i - 1, i, ""); + } + return s.toString(); + } else { + // Query the C model + IndexModel model = IndexModel.getDefault(); + IEditorInput input = fEditor.getEditorInput(); + if(input instanceof IFileEditorInput) { + IProject project = ((IFileEditorInput)input).getFile().getProject(); + + // Bail out quickly, if the project was deleted. + if (!project.exists()) + throw new CoreException(new Status(0, "", 0, "", null)); + + IProject[] refs = project.getReferencedProjects(); + + ITagEntry[] tags= model.query(project, expression, false, true); + + if(tags == null || tags.length == 0) { + for ( int j= 0; j < refs.length; j++ ) { + if (!refs[j].exists()) + continue; + tags= model.query(refs[j], expression, false, true); + if(tags != null && tags.length > 0) + break; + } + } + + if(tags != null && tags.length > 0) { + ITagEntry selectedTag = selectTag(tags); + // Show only the first element + StringBuffer s = new StringBuffer(); + s.append(expression + "() - " + selectedTag.getIFile().getFullPath().toString() + "[" + selectedTag.getLineNumber()+"]" ); + // Now add the pattern + s.append("\n\n" + selectedTag.getPattern()); + return s.toString(); + } + } + } + } + catch( BadLocationException x ) + { + // ignore + } + catch( CoreException x ) + { + // ignore + } + if ( expression != null && result != null ) + return expression + " = " + result; + return null; + } + + /** + * @see ITextHover#getHoverRegion(ITextViewer, int) + */ + public IRegion getHoverRegion( ITextViewer viewer, int offset ) + { + Point selectedRange = viewer.getSelectedRange(); + if ( selectedRange.x >= 0 && + selectedRange.y > 0 && + offset >= selectedRange.x && + offset <= selectedRange.x + selectedRange.y ) + return new Region( selectedRange.x, selectedRange.y ); + if ( viewer != null ) + return CWordFinder.findWord( viewer.getDocument(), offset ); + return null; + } + + private ITagEntry selectTag(ITagEntry[] tags) { + // Rules are to return a function prototype/declaration, and if + // not found first entry + for(int i = 0; i < tags.length; i++) { + if(tags[i].getKind() == TagFlags.T_PROTOTYPE) { + return tags[i]; + } + } + for(int i = 0; i < tags.length; i++) { + if(tags[i].getKind() == TagFlags.T_FUNCTION) { + return tags[i]; + } + } + return tags[0]; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/GotoErrorAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/GotoErrorAction.java new file mode 100644 index 00000000000..7e2d50e67c5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/GotoErrorAction.java @@ -0,0 +1,44 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextEditorAction; + + +public class GotoErrorAction extends TextEditorAction { + + + private boolean fForward; + + + public GotoErrorAction(String prefix, boolean forward) { + super(CPlugin.getResourceBundle(), prefix, null); + fForward= forward; + } + /** + * @see Action#run() + */ + public void run() { + CEditor e= (CEditor) getTextEditor(); + e.gotoError(fForward); + } + /** + * @see TextEditorAction#setEditor(ITextEditor) + */ + public void setEditor(ITextEditor editor) { + if (editor instanceof CEditor) + super.setEditor(editor); + } + /** + * @see TextEditorAction#update() + */ + public void update() { + setEnabled(true); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPainter.java new file mode 100644 index 00000000000..429cdf843e9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPainter.java @@ -0,0 +1,26 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +public interface IPainter { + + /** Paint reasons */ + int SELECTION= 0; + int TEXT_CHANGE= 1; + int KEY_STROKE= 2; + int MOUSE_BUTTON= 4; + int INTERNAL= 8; + + + void dispose(); + + void paint(int reason); + + void deactivate(boolean redraw); + + void setPositionManager(IPositionManager manager); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPositionManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPositionManager.java new file mode 100644 index 00000000000..bc495ee970a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IPositionManager.java @@ -0,0 +1,18 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.Position; + + +public interface IPositionManager { + + void addManagedPosition(Position position); + + void removeManagedPosition(Position position); +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IProblemAnnotation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IProblemAnnotation.java new file mode 100644 index 00000000000..6a0fe829215 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IProblemAnnotation.java @@ -0,0 +1,28 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Interface of annotations representing problems. + */ +public interface IProblemAnnotation { + + String getMessage(); + + int getId(); + + String[] getArguments(); + + boolean isTemporaryProblem(); + + boolean isWarning(); + + boolean isError(); + + boolean isProblem(); +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LexicalSortingAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LexicalSortingAction.java new file mode 100644 index 00000000000..345646df496 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LexicalSortingAction.java @@ -0,0 +1,82 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerSorter; + + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; + + +public class LexicalSortingAction extends Action { + + private static final String ACTION_NAME= "LexicalSortingAction"; + private static final String DIALOG_STORE_KEY= ACTION_NAME + ".sort"; + + private LexicalCSorter fSorter; + private TreeViewer fTreeViewer; + + public LexicalSortingAction(TreeViewer treeViewer) { + super(CPlugin.getResourceString(ACTION_NAME + ".label")); + + setDescription(CPlugin.getResourceString(ACTION_NAME + ".description")); + setToolTipText(CPlugin.getResourceString(ACTION_NAME + ".tooltip")); + + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_ALPHA_SORTING); + + fTreeViewer= treeViewer; + fSorter= new LexicalCSorter(); + + boolean checked= CPlugin.getDefault().getDialogSettings().getBoolean(DIALOG_STORE_KEY); + valueChanged(checked, false); + } + + public void run() { + valueChanged(isChecked(), true); + } + + private void valueChanged(boolean on, boolean store) { + setChecked(on); + fTreeViewer.setSorter(on ? fSorter : null); + + String key= ACTION_NAME + ".tooltip" + (on ? ".on" : ".off"); + setToolTipText(CPlugin.getResourceString(key)); + + if (store) { + CPlugin.getDefault().getDialogSettings().put(DIALOG_STORE_KEY, on); + } + } + + private class LexicalCSorter extends ViewerSorter { + public boolean isSorterProperty(Object element, Object property) { + return true; + } + + public int category(Object obj) { + if (obj instanceof ICElement) { + ICElement elem= (ICElement)obj; + switch (elem.getElementType()) { + case ICElement.C_MACRO: return 1; + case ICElement.C_INCLUDE: return 2; + + case ICElement.C_CLASS: return 3; + case ICElement.C_STRUCT: return 4; + case ICElement.C_UNION: return 5; + + case ICElement.C_FIELD: return 6; + case ICElement.C_FUNCTION: return 7; + } + + } + return 0; + } + }; + +}; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LinePainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LinePainter.java new file mode 100644 index 00000000000..3a4ddb43395 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/LinePainter.java @@ -0,0 +1,141 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.custom.LineBackgroundEvent; +import org.eclipse.swt.custom.LineBackgroundListener; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.StyledTextContent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.jface.text.source.ISourceViewer; + + +public class LinePainter implements IPainter, LineBackgroundListener { + + private StyledText fTextWidget; + private Color fHighlightColor; + private int[] fLine= { -1, -1 }; + private boolean fIsActive= false; + + + public LinePainter(ISourceViewer sourceViewer) { + fTextWidget= sourceViewer.getTextWidget(); + } + + public void setHighlightColor(Color highlightColor) { + fHighlightColor= highlightColor; + } + + /* + * @see LineBackgroundListener#lineGetBackground(LineBackgroundEvent) + */ + public void lineGetBackground(LineBackgroundEvent event) { + /* Don't use cached line information because of batched redrawing events. */ + + if (fTextWidget != null) { + + + int caret= fTextWidget.getCaretOffset(); + int length= event.lineText.length(); + + if (event.lineOffset <= caret && caret <= event.lineOffset + length && fIsActive) { + StyledTextContent content= fTextWidget.getContent(); + Point p= fTextWidget.getSelectionRange(); + if(content.getLineAtOffset(caret) == content.getLineAtOffset(p.x)) { + event.lineBackground= fHighlightColor; + } else { + event.lineBackground= fTextWidget.getBackground(); + } + } + else + event.lineBackground= fTextWidget.getBackground(); + } + } + + private void updateHighlightLine() { + StyledTextContent content= fTextWidget.getContent(); + + + int offset= fTextWidget.getCaretOffset(); + int length= content.getCharCount(); + if (offset > length) + offset= length; + + int lineNumber= content.getLineAtOffset(offset); + fLine[0]= content.getOffsetAtLine(lineNumber); + + try { + fLine[1]= content.getOffsetAtLine(lineNumber + 1); + } catch (IllegalArgumentException x) { + fLine[1]= -1; + } + } + + private void clearHighlightLine() { + if (fLine[0] <= fTextWidget.getCharCount()) + drawHighlightLine(); + } + + private void drawHighlightLine() { + if (fLine[1] >= fTextWidget.getCharCount()) + fLine[1]= -1; + + if (fLine[1] == -1) { + + Point upperLeft= fTextWidget.getLocationAtOffset(fLine[0]); + int width= fTextWidget.getClientArea().width; + int height= fTextWidget.getLineHeight(); + fTextWidget.redraw(upperLeft.x, upperLeft.y, width, height, false); + + } else { + fTextWidget.redrawRange(fLine[0], fLine[1] - fLine[0], true); + } + } + + /* + * @see IPainter#deactivate(boolean) + */ + public void deactivate(boolean redraw) { + if (fIsActive) { + fIsActive= false; + fTextWidget.removeLineBackgroundListener(this); + if (redraw) + drawHighlightLine(); + } + } + + /* + * @see IPainter#dispose() + */ + public void dispose() { + fTextWidget= null; + } + + /* + * @see IPainter#paint(int) + */ + public void paint(int reason) { + if (!fIsActive) { + fIsActive= true; + fTextWidget.addLineBackgroundListener(this); + } else if (fLine[0] != -1) { + clearHighlightLine(); + } + + updateHighlightLine(); + + drawHighlightLine(); + } + + /* + * @see IPainter#setPositionManager(IPositionManager) + */ + public void setPositionManager(IPositionManager manager) { + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java new file mode 100644 index 00000000000..6bb26d93f36 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenIncludeAction.java @@ -0,0 +1,204 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; + +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.cdt.internal.core.CommonMkInfo; + +import org.eclipse.cdt.internal.ui.dialogs.ElementListSelectionDialog; +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; + + +public class OpenIncludeAction extends Action { + + + private static final String PREFIX= "OpenIncludeAction."; + + private static final String DIALOG_TITLE= PREFIX + "dialog.title"; + private static final String DIALOG_MESSAGE= PREFIX + "dialog.message"; + + private ISelectionProvider fSelectionProvider; + + + public OpenIncludeAction(ISelectionProvider provider) { + super(CPlugin.getResourceString(PREFIX + "label")); + setDescription(CPlugin.getResourceString(PREFIX + "description")); + setToolTipText(CPlugin.getResourceString(PREFIX + "tooltip")); + + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_MENU_OPEN_INCLUDE); + + fSelectionProvider= provider; + } + + public void run() { + ICElement include= getIncludeStatement(fSelectionProvider.getSelection()); + if (include == null) { + return; + } + + try { + IResource res = include.getUnderlyingResource(); + ArrayList filesFound= new ArrayList(4); + if (res != null) { + findFile(res.getProject(), new Path(include.getElementName()), filesFound); + } + IFile fileToOpen; + int nElementsFound= filesFound.size(); + if (nElementsFound == 0) { + fileToOpen= null; + } else if (nElementsFound == 1) { + fileToOpen= (IFile) filesFound.get(0); + } else { + fileToOpen= chooseFile(filesFound); + } + + if (fileToOpen != null) { + EditorUtility.openInEditor(fileToOpen); + //IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + //if (window != null) { + // IWorkbenchPage p= window.getActivePage(); + // if (p != null) { + // p.openEditor(fileToOpen); + // } + //} + } else { // Try to get via the include path. + + + CommonMkInfo mk = null; + if (res != null) + mk = new CommonMkInfo(res.getProject().getLocation()); + else + mk = new CommonMkInfo(); + IPath[] paths = mk.getIncludePaths(); + + + IPath includePath = null; + for (int i = 0; i < paths.length; i++) { + if (res != null) { + // We've already scan the project. + if (paths[i].isPrefixOf(res.getProject().getLocation())) + continue; + } + IPath path = paths[i].append(include.getElementName()); + if (path.toFile().exists()) { + includePath = path; + break; + } + } + if (includePath != null) { + EditorUtility.openInEditor(includePath); + //IStorage s = new FileStorage(includePath); + //IEditorInput ei = new ExternalEditorInput(s); + //IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + //if (window != null) { + // IWorkbenchPage p = window.getActivePage(); + // if (p != null) { + // p.openEditor(ei, getEditorID(include.getName())); + // } + //} + } + } + } catch (CModelException e) { + CPlugin.log(e.getStatus()); + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + } + } + + private void findFile(IContainer parent, IPath name, ArrayList res) throws CoreException { + IResource found= parent.findMember(name); + if (found != null && found.getType() == IResource.FILE) { + res.add(found); + } + IResource[] children= parent.members(); + for (int i= 0; i < children.length; i++) { + if (children[i] instanceof IContainer) { + findFile((IContainer)children[i], name, res); + } + } + } + + + private IFile chooseFile(ArrayList filesFound) { + ILabelProvider renderer= new LabelProvider() { + public String getText(Object element) { + if (element instanceof IFile) { + IFile file= (IFile)element; + return file.getName() + " - " + file.getParent().getFullPath().toString(); + } + return super.getText(element); + } + }; + + ElementListSelectionDialog dialog= new ElementListSelectionDialog(CPlugin.getActiveWorkbenchShell(), renderer, false, false); + dialog.setTitle(CPlugin.getResourceString(DIALOG_TITLE)); + dialog.setMessage(CPlugin.getResourceString(DIALOG_MESSAGE)); + dialog.setElements(filesFound); + + if (dialog.open() == dialog.OK) { + return (IFile) dialog.getSelectedElement(); + } + return null; + } + + + private static ICElement getIncludeStatement(ISelection sel) { + if (!sel.isEmpty() && sel instanceof IStructuredSelection) { + List list= ((IStructuredSelection)sel).toList(); + if (list.size() == 1) { + Object element= list.get(0); + if (element instanceof ICElement && ((ICElement)element).getElementType() == ICElement.C_INCLUDE) { + return (ICElement)element; + } + } + } + return null; + } + + public static boolean canActionBeAdded(ISelection selection) { + return getIncludeStatement(selection) != null; + } + + + public static String getEditorID(String name) { + IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); + if (registry != null) { + IEditorDescriptor descriptor = registry.getDefaultEditor(name); + if (descriptor != null) { + return descriptor.getId(); + } else { + return registry.getDefaultEditor().getId(); + } + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenOnSelectionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenOnSelectionAction.java new file mode 100644 index 00000000000..4605fe309cb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OpenOnSelectionAction.java @@ -0,0 +1,270 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.core.index.IndexModel; +import org.eclipse.cdt.core.index.TagFlags; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.dialogs.ElementListSelectionDialog; +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.PartInitException; + + +/** + * This action opens a java editor on the element represented by text selection of + * the connected java source viewer. + * + * Use action from package org.eclipse.jdt.ui.actions + */ +public class OpenOnSelectionAction extends Action { + + private class TagEntryLabelProvider extends LabelProvider { + + public TagEntryLabelProvider() { + } + + public Image getImage(Object element) { + if(element instanceof ITagEntry) { + int kind = ((ITagEntry)element).getKind(); + switch (kind) { + case TagFlags.T_PROTOTYPE: + return CPluginImages.get(CPluginImages.IMG_OBJS_DECLARATION); + case TagFlags.T_CLASS: + return CPluginImages.get(CPluginImages.IMG_OBJS_CLASS); + case TagFlags.T_ENUM: + case TagFlags.T_VARIABLE: + case TagFlags.T_MEMBER: + return CPluginImages.get(CPluginImages.IMG_OBJS_FIELD); + case TagFlags.T_FUNCTION: + return CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION); + case TagFlags.T_STRUCT: + return CPluginImages.get(CPluginImages.IMG_OBJS_STRUCT); + case TagFlags.T_UNION: + return CPluginImages.get(CPluginImages.IMG_OBJS_UNION); + case TagFlags.T_MACRO: + return CPluginImages.get(CPluginImages.IMG_OBJS_MACRO); + } + } + return CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION); + } + + public String getText(Object element) { + if(element instanceof ITagEntry) { + ITagEntry entry = (ITagEntry) element; + if(entry.getIFile() != null) { + return entry.getIFile().getName() + " [" + entry.getLineNumber() + "] - " + entry.getIFile().getFullPath().toOSString(); + } + return entry.getFileName() + " [" + entry.getLineNumber() + "]"; + } else { + return ""; + } + } + }; + + private String fDialogTitle; + private String fDialogMessage; + protected CEditor fEditor; + + + /** + * Creates a new action with the given label and image. + */ + protected OpenOnSelectionAction() { + super(); + + setText(CEditorMessages.getString("OpenOnSelection.label")); //$NON-NLS-1$ + setToolTipText(CEditorMessages.getString("OpenOnSelection.tooltip")); //$NON-NLS-1$ + setDescription(CEditorMessages.getString("OpenOnSelection.description")); //$NON-NLS-1$ + setDialogTitle(CEditorMessages.getString("OpenOnSelection.dialog.title")); //$NON-NLS-1$ + setDialogMessage(CEditorMessages.getString("OpenOnSelection.dialog.message")); //$NON-NLS-1$ + } + + /** + * Creates a new action with the given image. + */ + public OpenOnSelectionAction(ImageDescriptor image) { + this(); + setImageDescriptor(image); + } + + /** + * Creates a new action with the given editor + */ + public OpenOnSelectionAction(CEditor editor) { + this(); + fEditor = editor; + } + + /** + * Creates a new action without label. Initializing is + * subclass responsibility. + */ + protected void OOpenOnSelectionAction(String label) { + //this(); + //super(label); + } + + protected void setDialogTitle(String title) { + fDialogTitle= title; + } + + protected void setDialogMessage(String message) { + fDialogMessage= message; + } + + public void setContentEditor(CEditor editor) { + fEditor= editor; + } + + /** + * @see IAction#actionPerformed + */ + public void run() { + + IndexModel model = IndexModel.getDefault(); + if (model != null && fEditor.getSelectionProvider() != null) { + ITextSelection selection= (ITextSelection) fEditor.getSelectionProvider().getSelection(); + try { + String sel = selection.getText(); + IFile file = fEditor.getInputFile(); + if(file == null) + return; + IProject project = file.getProject(); + if(project == null) + return; + ITagEntry[] result= model.query(project,sel); + + List filtered = new ArrayList(); + if (result != null && result.length > 0) { + filterResolveResults(result, filtered); + } + + IProject[] p = project.getReferencedProjects(); + for ( int j= 0; j < p.length; j++ ) { + result= model.query(p[j],sel); + if (result != null && result.length > 0) { + filterResolveResults(result, filtered); + } + } + + if (filtered.isEmpty() == false) { + ITagEntry selected= selectCElement(filtered, getShell(), fDialogTitle, fDialogMessage); + if (selected != null) { + open(selected); + return; + } + } + } catch (CModelException x) { + CPlugin.log(x.getStatus()); + } catch (PartInitException x) { + CPlugin.log(x); + } catch (CoreException x) { + CPlugin.log(x); + } + } + + getShell().getDisplay().beep(); + } + + protected Shell getShell() { + return fEditor.getSite().getShell(); + } + + + + /** + * Opens the editor on the given element and subsequently selects it. + */ + protected void open(ITagEntry element) throws CModelException, PartInitException { + IEditorPart part= EditorUtility.openInEditor(element.getIFile()); + int line = element.getLineNumber(); + if(line > 0) line--; + if(part instanceof CEditor) { + CEditor ed = (CEditor)part; + + try { + IDocument document= ed.getDocumentProvider().getDocument(ed.getEditorInput()); + if(line > 3) { + ed.selectAndReveal(document.getLineOffset(line - 3), 0); + } + ed.selectAndReveal(document.getLineOffset(line), 0); + } catch (BadLocationException e) {} + } + } + + /** + * Filters out source references from the given code resolve results. + * A utility method that can be called by subclassers. + */ + protected List filterResolveResults(ITagEntry[] codeResolveResults, List list) { + int nResults= codeResolveResults.length; + List refs= list; + for (int i= 0; i < nResults; i++) { + if (codeResolveResults[i].getKind() != TagFlags.T_PROTOTYPE) { + refs.add(codeResolveResults[i]); + } + } + return refs; + } + + /** + * Shows a dialog for resolving an ambigous C element. + * Utility method that can be called by subclassers. + */ + protected ITagEntry selectCElement(List elements, Shell shell, String title, String message) { + + int nResults= elements.size(); + + if (nResults == 0) + return null; + + if (nResults == 1) + return (ITagEntry) elements.get(0); + + //int flags= CElementLabelProvider.SHOW_DEFAULT + // | CElementLabelProvider.SHOW_QUALIFIED + // | CElementLabelProvider.SHOW_ROOT; + + ElementListSelectionDialog dialog= new ElementListSelectionDialog(shell, new TagEntryLabelProvider(), false, false); + dialog.setTitle(title); + dialog.setMessage(message); + dialog.setElements(elements); + + if (dialog.open() == dialog.OK) { + Object[] selection= dialog.getResult(); + if (selection != null && selection.length > 0) { + nResults= selection.length; + for (int i= 0; i < nResults; i++) { + Object current= selection[i]; + if (current instanceof ITagEntry) + return (ITagEntry) current; + } + } + } + return null; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PaintManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PaintManager.java new file mode 100644 index 00000000000..0c808be9d5e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PaintManager.java @@ -0,0 +1,257 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.widgets.Control; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; + + +public final class PaintManager implements KeyListener, MouseListener, ISelectionChangedListener, ITextListener, ITextInputListener { + + static class PositionManager implements IPositionManager { + + private IDocument fDocument; + private IPositionUpdater fPositionUpdater; + private String fCategory; + + public PositionManager() { + fCategory= getClass().getName() + hashCode(); + fPositionUpdater= new DefaultPositionUpdater(fCategory); + } + + public void install(IDocument document) { + fDocument= document; + fDocument.addPositionCategory(fCategory); + fDocument.addPositionUpdater(fPositionUpdater); + } + + public void dispose() { + uninstall(fDocument); + } + + public void uninstall(IDocument document) { + if (document == fDocument && document != null) { + try { + fDocument.removePositionUpdater(fPositionUpdater); + fDocument.removePositionCategory(fCategory); + } catch (BadPositionCategoryException x) { + // should not happen + } + fDocument= null; + } + } + + /* + * @see IPositionManager#addManagedPosition(Position) + */ + public void addManagedPosition(Position position) { + try { + fDocument.addPosition(fCategory, position); + } catch (BadPositionCategoryException x) { + // should not happen + } catch (BadLocationException x) { + // should not happen + } + } + + /* + * @see IPositionManager#removeManagedPosition(Position) + */ + public void removeManagedPosition(Position position) { + try { + fDocument.removePosition(fCategory, position); + } catch (BadPositionCategoryException x) { + // should not happen + } + } + }; + + + private List fPainters= new ArrayList(2); + private PositionManager fManager; + private ISourceViewer fSourceViewer; + private boolean fTextChanged= false; + private boolean fAutoRepeat= false; + + + public PaintManager(ISourceViewer sourceViewer) { + fSourceViewer= sourceViewer; + } + + public void addPainter(IPainter painter) { + if (!fPainters.contains(painter)) { + fPainters.add(painter); + if (fPainters.size() == 1) + install(); + painter.setPositionManager(fManager); + painter.paint(IPainter.INTERNAL); + } + } + + public void removePainter(IPainter painter) { + if (fPainters.remove(painter)) + painter.setPositionManager(null); + if (fPainters.size() == 0) + dispose(); + } + + private void install() { + + fManager= new PositionManager(); + fManager.install(fSourceViewer.getDocument()); + + fSourceViewer.addTextInputListener(this); + + ISelectionProvider provider= fSourceViewer.getSelectionProvider(); + provider.addSelectionChangedListener(this); + + fSourceViewer.addTextListener(this); + + StyledText text= fSourceViewer.getTextWidget(); + text.addKeyListener(this); + text.addMouseListener(this); + } + + public void dispose() { + + if (fManager != null) { + fManager.dispose(); + fManager= null; + } + + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).dispose(); + fPainters.clear(); + + fSourceViewer.removeTextInputListener(this); + + ISelectionProvider provider= fSourceViewer.getSelectionProvider(); + if (provider != null) + provider.removeSelectionChangedListener(this); + + fSourceViewer.removeTextListener(this); + + StyledText text= fSourceViewer.getTextWidget(); + if (text != null && !text.isDisposed()) { + text.removeKeyListener(this); + text.removeMouseListener(this); + } + } + + private void paint(int reason) { + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).paint(reason); + } + + /* + * @see KeyListener#keyPressed(KeyEvent) + */ + public void keyPressed(KeyEvent e) { + // This leaves artifacts when scrolling + //if (fAutoRepeat) + paint(IPainter.KEY_STROKE); + + fTextChanged= false; + fAutoRepeat= true; + } + + /* + * @see KeyListener#keyReleased(KeyEvent) + */ + public void keyReleased(KeyEvent e) { + fAutoRepeat= false; + if (!fTextChanged) + paint(IPainter.KEY_STROKE); + } + + /* + * @see MouseListener#mouseDoubleClick(MouseEvent) + */ + public void mouseDoubleClick(MouseEvent e) { + } + + /* + * @see MouseListener#mouseDown(MouseEvent) + */ + public void mouseDown(MouseEvent e) { + } + + /* + * @see MouseListener#mouseUp(MouseEvent) + */ + public void mouseUp(MouseEvent e) { + paint(IPainter.MOUSE_BUTTON); + } + + /* + * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + paint(IPainter.SELECTION); + } + + /* + * @see ITextListener#textChanged(TextEvent) + */ + public void textChanged(TextEvent event) { + fTextChanged= true; + Control control= fSourceViewer.getTextWidget(); + if (control != null) { + control.getDisplay().asyncExec(new Runnable() { + public void run() { + if (fTextChanged && fSourceViewer != null) + paint(IPainter.TEXT_CHANGE); + } + }); + } + } + + /* + * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument, IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput != null) { + for (Iterator e = fPainters.iterator(); e.hasNext();) + ((IPainter) e.next()).deactivate(false); + fManager.uninstall(oldInput); + } + } + + /* + * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput != null) { + fManager.install(newInput); + paint(IPainter.TEXT_CHANGE); + } + } +} + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PrintMarginPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PrintMarginPainter.java new file mode 100644 index 00000000000..0f96d01cc21 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/PrintMarginPainter.java @@ -0,0 +1,128 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; + +import org.eclipse.jface.text.source.ISourceViewer; + + + +public class PrintMarginPainter implements IPainter, PaintListener { + + + private StyledText fTextWidget; + + private int fMarginWidth= 80; + private Color fColor; + private int fLineStyle= SWT.LINE_SOLID; + private int fLineWidth= 1; + + private int fCachedWidgetX= -1; + private boolean fIsActive= false; + + public PrintMarginPainter(ISourceViewer sourceViewer) { + fTextWidget= sourceViewer.getTextWidget(); + } + + public void setMarginRulerColumn(int width) { + fMarginWidth= width; + intialize(); + } + + public void setMarginRulerStyle(int lineStyle) { + fLineStyle= lineStyle; + } + + public void setMarginRulerWidth(int lineWidth) { + fLineWidth= lineWidth; + } + + /** + * Must be called before paint is called the first time. + */ + public void setMarginRulerColor(Color color) { + fColor= color; + } + + /** + * Must be called explicitly when font of text widget changes. + */ + public void intialize() { + computeWidgetX(); + fTextWidget.redraw(); + } + + private void computeWidgetX() { + GC gc= new GC(fTextWidget); + int pixels= gc.getFontMetrics().getAverageCharWidth(); + gc.dispose(); + + fCachedWidgetX= pixels * fMarginWidth; + } + + /* + * @see IPainter#deactivate(boolean) + */ + public void deactivate(boolean redraw) { + if (fIsActive) { + fIsActive= false; + fTextWidget.removePaintListener(this); + if (redraw) + fTextWidget.redraw(); + } + } + + /* + * @see IPainter#dispose() + */ + public void dispose() { + fTextWidget= null; + } + + /* + * @see IPainter#paint(int) + */ + public void paint(int reason) { + if (!fIsActive) { + fIsActive= true; + fTextWidget.addPaintListener(this); + if (fCachedWidgetX == -1) + computeWidgetX(); + fTextWidget.redraw(); + } + } + + /* + * @see IPainter#setPositionManager(IPositionManager) + */ + public void setPositionManager(IPositionManager manager) { + } + + /* + * @see PaintListener#paintControl(PaintEvent) + */ + public void paintControl(PaintEvent e) { + if (fTextWidget != null) { + int x= fCachedWidgetX - fTextWidget.getHorizontalPixel(); + if (x >= 0) { + Rectangle area= fTextWidget.getClientArea(); + e.gc.setForeground(fColor); + e.gc.setLineStyle(fLineStyle); + e.gc.setLineWidth(fLineWidth); + e.gc.drawLine(x, 0, x, area.height); + } + } + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemAnnotationIterator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemAnnotationIterator.java new file mode 100644 index 00000000000..1f9642a6ac0 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemAnnotationIterator.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Iterator; +import org.eclipse.jface.text.source.IAnnotationModel; + + +/** + * Filters problems based on their types. + */ +public class ProblemAnnotationIterator implements Iterator { + + private Iterator fIterator; + private IProblemAnnotation fNext; + + public ProblemAnnotationIterator(IAnnotationModel model) { + fIterator= model.getAnnotationIterator(); + skip(); + } + + private void skip() { + while (fIterator.hasNext()) { + Object next= fIterator.next(); + if (next instanceof IProblemAnnotation) { + fNext= (IProblemAnnotation) next; + return; + } + } + fNext= null; + } + + /* + * @see Iterator#hasNext() + */ + public boolean hasNext() { + return fNext != null; + } + + /* + * @see Iterator#next() + */ + public Object next() { + try { + return fNext; + } finally { + skip(); + } + } + + /* + * @see Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemPainter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemPainter.java new file mode 100644 index 00000000000..b17fab4d779 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ProblemPainter.java @@ -0,0 +1,245 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModelListener; +import org.eclipse.jface.text.source.ISourceViewer; + +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + +//import org.eclipse.jdt.core.compiler.IProblem; + + +/** + * Highlights the temporary problems. + */ +public class ProblemPainter implements IPainter, PaintListener, IAnnotationModelListener { + + private boolean fIsActive= false; + private boolean fIsPainting= false; + private boolean fIsModelChanging= false; + + private Color fColor; + private ITextEditor fTextEditor; + private ISourceViewer fSourceViewer; + private StyledText fTextWidget; + private IAnnotationModel fModel; + private List fProblemPositions= new ArrayList(); + + + + public ProblemPainter(ITextEditor textEditor, ISourceViewer sourceViewer) { + fTextEditor= textEditor; + fSourceViewer= sourceViewer; + fTextWidget= sourceViewer.getTextWidget(); + } + + private boolean hasProblems() { + return !fProblemPositions.isEmpty(); + } + + private void enablePainting() { + if (!fIsPainting && hasProblems()) { + fIsPainting= true; + fTextWidget.addPaintListener(this); + handleDrawRequest(null); + } + } + + private void disablePainting(boolean redraw) { + if (fIsPainting) { + fIsPainting= false; + fTextWidget.removePaintListener(this); + if (redraw && hasProblems()) + handleDrawRequest(null); + } + } + + private void setModel(IAnnotationModel model) { + + if (fModel != model) { + if (fModel != null) + fModel.removeAnnotationModelListener(this); + fModel= model; + if (fModel != null) + fModel.addAnnotationModelListener(this); + } + + if (fProblemPositions != null) { + fProblemPositions.clear(); + if (fModel != null) { + Iterator e= new ProblemAnnotationIterator(fModel); + while (e.hasNext()) { + IProblemAnnotation pa= (IProblemAnnotation) e.next(); + if (pa.isProblem()) { + Annotation a= (Annotation) pa; + Position p= fModel.getPosition(a); + fProblemPositions.add(p); + } + } + } + } + } + + /* + * @see IAnnotationModelListener#modelChanged(IAnnotationModel) + */ + public void modelChanged(final IAnnotationModel model) { + if (fTextWidget != null && !fTextWidget.isDisposed() && !fIsModelChanging) { + Display d= fTextWidget.getDisplay(); + if (d != null) { + d.asyncExec(new Runnable() { + public void run() { + disablePainting(true); + try { + fIsModelChanging= true; + setModel(model); + } finally { + fIsModelChanging= false; + } + enablePainting(); + } + }); + } + } + } + + public void setHighlightColor(Color color) { + fColor= color; + } + + /* + * @see IPainter#dispose() + */ + public void dispose() { + fColor= null; + fTextWidget= null; + fModel= null; + fProblemPositions= null; + } + + /* + * @see PaintListener#paintControl(PaintEvent) + */ + public void paintControl(PaintEvent event) { + if (fTextWidget != null) + handleDrawRequest(event.gc); + } + + private void handleDrawRequest(GC gc) { + + IRegion region= fSourceViewer.getVisibleRegion(); + int offset= region.getOffset(); + int length= region.getLength(); + + for (Iterator e = fProblemPositions.iterator(); e.hasNext();) { + Position p = (Position) e.next(); + if (p.overlapsWith(offset, length)) { + int p1= Math.max(offset, p.getOffset()); + int p2= Math.min(offset + length, p.getOffset() + p.getLength()); + draw(gc, p1 - offset, p2 - p1); + } + } + } + + private int[] computePolyline(Point left, Point right, int height) { + + final int WIDTH= 4; // must be even + final int HEIGHT= 2; // can be any number + + int leftX= left.x; + int peeks= (right.x - left.x) / WIDTH; + + // compute (number of point) * 2 + int length= ((2 * peeks) + 1) * 2; + if (length < 0) + return new int[0]; + + int[] coordinates= new int[length]; + + // cache peeks' y-coordinates + int bottom= left.y + height - 1; + int top= bottom - HEIGHT; + + // populate array with peek coordinates + for (int i= 0; i < peeks; i++) { + int index= 4 * i; + coordinates[index]= leftX + (WIDTH * i); + coordinates[index+1]= bottom; + coordinates[index+2]= coordinates[index] + WIDTH/2; + coordinates[index+3]= top; + } + + // the last down flank is missing + coordinates[length-2]= left.x + (WIDTH * peeks); + coordinates[length-1]= bottom; + + return coordinates; + } + + private void draw(GC gc, int offset, int length) { + if (gc != null) { + + Point left= fTextWidget.getLocationAtOffset(offset); + Point right= fTextWidget.getLocationAtOffset(offset + length); + + gc.setForeground(fColor); + int[] polyline= computePolyline(left, right, gc.getFontMetrics().getHeight()); + gc.drawPolyline(polyline); + + } else { + fTextWidget.redrawRange(offset, length, true); + } + } + + /* + * @see IPainter#deactivate(boolean) + */ + public void deactivate(boolean redraw) { + if (fIsActive) { + fIsActive= false; + disablePainting(redraw); + setModel(null); + } + } + + /* + * @see IPainter#paint(int) + */ + public void paint(int reason) { + if (!fIsActive) { + fIsActive= true; + IDocumentProvider provider= fTextEditor.getDocumentProvider(); + setModel(provider.getAnnotationModel(fTextEditor.getEditorInput())); + enablePainting(); + } + } + + /* + * @see IPainter#setPositionManager(IPositionManager) + */ + public void setPositionManager(IPositionManager manager) { + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SearchForReferencesAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SearchForReferencesAction.java new file mode 100644 index 00000000000..bed0f603bb7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SearchForReferencesAction.java @@ -0,0 +1,157 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +//import org.eclipse.search.internal.core.text.TextSearchEngine; +import org.eclipse.search.internal.core.text.TextSearchScope; +import org.eclipse.search.internal.ui.text.TextSearchOperation; +import org.eclipse.search.internal.ui.text.TextSearchResultCollector; +import org.eclipse.search.internal.ui.util.ExceptionHandler; +import org.eclipse.search.ui.SearchUI; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.PlatformUI; + + + +public class SearchForReferencesAction extends Action { + + + private static final String PREFIX= "SearchForReferencesAction."; + + private static final String DIALOG_TITLE= PREFIX + "dialog.title"; + private static final String DIALOG_MESSAGE= PREFIX + "dialog.message"; + + private ISelectionProvider fSelectionProvider; + + + public SearchForReferencesAction(ISelectionProvider provider) { + super(CPlugin.getResourceString(PREFIX + "label")); + setDescription(CPlugin.getResourceString(PREFIX + "description")); + setToolTipText(CPlugin.getResourceString(PREFIX + "tooltip")); + + if(provider instanceof CContentOutlinePage) { + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_MENU_OPEN_INCLUDE); + setText("Search for References"); // $NON-NLS + } + + fSelectionProvider= provider; + } + + public void run() { + String search_name; + + ISelection selection= fSelectionProvider.getSelection(); + if(selection instanceof ITextSelection) { + search_name = ((ITextSelection)selection).getText(); + if(search_name.length() == 0) return; + } else { + ICElement element= getElement(selection); + if (element == null) { + return; + } + search_name = element.getElementName(); + } + + // @@@ we rely on the internal functions of the Search plugin, since + // none of these are actually exported. This is probably going to change + // with 2.0. + TextSearchResultCollector col = new TextSearchResultCollector(); + try { + //TextSearchPage + //ProgressMonitor monitor = new ProgressMonitor(); + //col.setProgressMonitor(monitor) + SearchUI.activateSearchResultView(); + //col.aboutToStart(); + + // We now have the element, start a search on the string + //TextSearchEngine engine = new TextSearchEngine(); + TextSearchScope scope= TextSearchScope.newWorkspaceScope(); + // Add the extensions from the C editor definition for now + scope.addExtension("c"); + scope.addExtension("h"); + scope.addExtension("cc"); + scope.addExtension("hh"); + + TextSearchOperation op= new TextSearchOperation( + CPlugin.getWorkspace(), + search_name, + "", + scope, + col); + + + //engine.search(CPlugin.getWorkspace(), element.getName(), + // null, scope, col); + IRunnableContext context= null; + //context= getContainer().getRunnableContext(); + + Shell shell= new Shell(); // getShell(); + if (context == null) + context= new ProgressMonitorDialog(shell); + + + try { + context.run(true, true, op); + } catch (InvocationTargetException ex) { + ExceptionHandler.handle(ex, "Error","Error"); //$NON-NLS-2$ //$NON-NLS-1$ + } catch (InterruptedException e) { + } + } catch (Exception e) {} + + } + + + private static ICElement getElement(ISelection sel) { + if (!sel.isEmpty() && sel instanceof IStructuredSelection) { + List list= ((IStructuredSelection)sel).toList(); + if (list.size() == 1) { + Object element= list.get(0); + if (element instanceof ICElement) { + return (ICElement)element; + } + } + } + return null; + } + + public static boolean canActionBeAdded(ISelection selection) { + if(selection instanceof ITextSelection) { + return (((ITextSelection)selection).getLength() > 0); + } else { + return getElement(selection) != null; + } + } + + + public static String getEditorID(String name) { + IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); + if (registry != null) { + IEditorDescriptor descriptor = registry.getDefaultEditor(name); + if (descriptor != null) { + return descriptor.getId(); + } else { + return registry.getDefaultEditor().getId(); + } + } + return null; + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SetConditionAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SetConditionAction.java new file mode 100644 index 00000000000..2eb512c6822 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SetConditionAction.java @@ -0,0 +1,410 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + + +public class SetConditionAction extends Action +{ + class BreakpointConditionDialog + { + Shell fShell; + String fOldCondition; + String fCondition; + String fOldIgnoreCount; + String fIgnoreCount; + Button fOkButton; + Button fCancelButton; + boolean fIsCanceled = true; + String fTitle = "Breakpoint condition"; + public BreakpointConditionDialog( Shell parent, + Point location, + String condition, + int ignoreCount ) + { + fOldCondition = condition; + fCondition = condition; + fOldIgnoreCount = String.valueOf( ignoreCount ); + fIgnoreCount = fOldIgnoreCount; + fShell = new Shell( parent, SWT.DIALOG_TRIM | SWT.PRIMARY_MODAL ); + fShell.setText( fTitle ); + fShell.setLayout( new GridLayout() ); + fShell.setLocation( location ); + } + + + private void createControlButtons() + { + Composite composite = new Composite( fShell, SWT.NULL ); + composite.setLayoutData( new GridData( GridData.HORIZONTAL_ALIGN_CENTER ) ); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + composite.setLayout( layout ); + + fOkButton = new Button( composite, SWT.PUSH ); + fOkButton.setText( "OK" ); + fOkButton.addSelectionListener( + new SelectionAdapter() + { + public void widgetSelected( SelectionEvent event ) + { + try + { + Integer.parseInt( fIgnoreCount ); + } + catch( NumberFormatException e ) + { + MessageDialog.openError( fShell, fTitle, "Invalid integer value - " + e.getMessage() ); + return; + } + fIsCanceled = false; + fShell.close(); + } + } ); + + fCancelButton = new Button( composite, SWT.PUSH ); + fCancelButton.setText( "Cancel" ); + fCancelButton.addSelectionListener( + new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + fCondition = fOldCondition; + fIgnoreCount = fOldIgnoreCount; + fShell.close(); + } + } ); + + fShell.setDefaultButton( fOkButton ); + } + + + private void createTextWidgets() + { + Composite composite = new Composite( fShell, SWT.NULL ); + composite.setLayoutData( new GridData( GridData.FILL_VERTICAL ) ); + GridLayout layout= new GridLayout(); + layout.numColumns = 1; + composite.setLayout( layout ); + + Label label = new Label( composite, SWT.RIGHT ); + label.setText( "Enter condition to be evaluated:" ); + Text textCondition = new Text( composite, SWT.BORDER ); + label = new Label( composite, SWT.RIGHT ); + label.setText( "Enter the number of times to skip before stopping:" ); + Text textIgnoreCount = new Text( composite, SWT.BORDER ); + GridData condGridData = new GridData(); + condGridData.widthHint = 300; + textCondition.setLayoutData( condGridData ); + textCondition.setText( fCondition ); + addTextListener( textCondition, true ); + GridData ignoreGridData = new GridData(); + ignoreGridData.widthHint = 50; + textIgnoreCount.setLayoutData( ignoreGridData ); + textIgnoreCount.setText( fIgnoreCount ); + addTextListener( textIgnoreCount, false ); + } + + + private void addTextListener( final Text text, final boolean isCondition ) + { + text.addModifyListener( + new ModifyListener() + { + public void modifyText( ModifyEvent e ) + { + if ( isCondition ) + fCondition = text.getText(); + else + { + fIgnoreCount = text.getText(); + fOkButton.setEnabled( fIgnoreCount.length() > 0 ); + } + } + } ); + } + + + public String getCondition() + { + return fCondition; + } + + public int getIgnoreCount() + { + int ret = 0; + try + { + ret = Integer.parseInt( fIgnoreCount ); + } + catch( NumberFormatException e ) + { + } + + return ret; + } + + + public boolean open() + { + createTextWidgets(); + createControlButtons(); + fShell.pack(); + fShell.open(); + Display display = fShell.getDisplay(); + while( !fShell.isDisposed() ) + { + if( !display.readAndDispatch() ) + display.sleep(); + } + + return !fIsCanceled; + } + } + + + private IVerticalRuler fRuler; + private ITextEditor fTextEditor; + + + public SetConditionAction( IVerticalRuler ruler, ITextEditor editor ) + { + super( "Set condition ..." ); + fRuler = ruler; + fTextEditor = editor; + } + + + public boolean isBreakpointSet() + { + List markers = getMarkers(); + return ( markers != null && markers.size() > 0 ); + } + + + protected IResource getResource() + { + IEditorInput input = fTextEditor.getEditorInput(); + + IResource resource = (IResource)input.getAdapter( IFile.class ); + + if ( resource == null ) + resource = (IResource)input.getAdapter( IResource.class ); + + return resource; + } + + + protected ITextEditor getTextEditor() + { + return fTextEditor; + } + + + protected IVerticalRuler getVerticalRuler() + { + return fRuler; + } + + + protected IDocument getDocument() + { + IDocumentProvider provider = fTextEditor.getDocumentProvider(); + return provider.getDocument( fTextEditor.getEditorInput() ); + } + + + protected AbstractMarkerAnnotationModel getAnnotationModel() + { + IDocumentProvider provider = fTextEditor.getDocumentProvider(); + IAnnotationModel model = provider.getAnnotationModel( fTextEditor.getEditorInput() ); + if ( model instanceof AbstractMarkerAnnotationModel ) + return (AbstractMarkerAnnotationModel)model; + return null; + } + + + /** + * Returns all breakpoint markers which include the ruler's line of activity. + * + * @returns all breakpoint markers which include the ruler's line of activity + */ + protected List getMarkers() + { + List markers = new ArrayList(); + + + IResource resource = getResource(); + IDocument document = getDocument(); + AbstractMarkerAnnotationModel model = getAnnotationModel(); + + + if ( resource != null && model != null ) + { + try + { + IMarker[] allMarkers = resource.findMarkers( IBreakpoint.BREAKPOINT_MARKER, + true, + IResource.DEPTH_ZERO ); + if ( allMarkers != null ) + { + for ( int i = 0; i < allMarkers.length; i++ ) + { + if ( includesRulerLine( model.getMarkerPosition( allMarkers[i] ), document ) ) + { + markers.add( allMarkers[i] ); + } + } + } + } + catch( CoreException x ) + { + handleCoreException( x, "SetConditionAction:getMarkers" ); + } + } + + + return markers; + } + + + protected boolean includesRulerLine( Position position, IDocument document ) + { + if ( position != null ) + { + try + { + int markerLine = document.getLineOfOffset( position.getOffset() ); + int line = fRuler.getLineOfLastMouseButtonActivity(); + if ( line == markerLine ) + return true; + return ( markerLine <= line && line <= document.getLineOfOffset( position.getOffset() + position.getLength() ) ); + } + catch( BadLocationException x ) + { + } + } + return false; + } + + + protected void handleCoreException( CoreException exception, String message ) + { + ILog log = Platform.getPlugin( PlatformUI.PLUGIN_ID ).getLog(); + + if ( message != null ) + log.log( new Status( IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, null ) ); + + log.log( exception.getStatus() ); +/* + Shell shell = getTextEditor().getSite().getShell(); + String title = getString( fBundle, fPrefix + "error.dialog.title", fPrefix + "error.dialog.title" ); + String msg = getString( fBundle, fPrefix + "error.dialog.message", fPrefix + "error.dialog.message" ); + + ErrorDialog.openError( shell, title, msg, exception.getStatus() ); +*/ + } + + + protected Shell getShell() + { + IWorkbench workbench = PlatformUI.getWorkbench(); + if ( workbench != null ) + { + IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); + if ( window != null ) + { + Shell shell = window.getShell(); + if ( !shell.isDisposed() ) + { + return shell; + } + } + } + return null; + } + + + /** + * @see Action#run() + */ + public void run() + { + try + { + Object[] markers = getMarkers().toArray(); + if ( markers.length == 0 ) + return; + IMarker marker = (IMarker)markers[0]; + Shell shell = getShell(); + if ( shell == null ) + return; + Point location = shell.getDisplay().getCursorLocation(); + String condition = marker.getAttribute( "condition", "" ); + int ignoreCount = marker.getAttribute( "ignoreCount", 0 ); + BreakpointConditionDialog dialog = + new BreakpointConditionDialog( shell, location, condition, ignoreCount ); + if ( dialog.open() ) + { + condition = dialog.getCondition(); + marker.setAttribute( "condition", condition ); + ignoreCount = dialog.getIgnoreCount(); + marker.setAttribute( "ignoreCount", ignoreCount ); + String message = ""; + if ( condition.length() > 0 ) + message += "if " + condition + " "; + if ( ignoreCount > 0 ) + message += "ignore = " + ignoreCount; + marker.setAttribute( IMarker.MESSAGE, message ); + } + } + catch( CoreException e ) + { + } + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/StatusLineContributionItem.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/StatusLineContributionItem.java new file mode 100644 index 00000000000..ef513f7e0d8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/StatusLineContributionItem.java @@ -0,0 +1,98 @@ +package org.eclipse.cdt.internal.ui.editor; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/* + * This code is temporarily here to provide some editor line/column numbers. + * This is all in Eclipse 2.0, so we remove it when we move forward to that version. + */ + + +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.texteditor.IStatusField; + + + +/** + * Contribution item for the status line. + */ +public class StatusLineContributionItem extends ContributionItem implements IStatusField { + + + static class StatusLineLabel extends CLabel { + + private static int INDENT= 3; // left and right margin used in CLabel + + private Point fFixedSize; + + public StatusLineLabel(Composite parent, int style) { + super(parent, style); + + GC gc= new GC(parent); + gc.setFont(parent.getFont()); + Point extent= gc.textExtent("MMMMMMMMM"); + gc.dispose(); + + fFixedSize= new Point(extent.x + INDENT * 2, 10); + } + + public Point computeSize(int wHint, int hHint, boolean changed) { + return fFixedSize; + } + }; + + private String fText; + private Image fImage; + private StatusLineLabel fLabel; + + /** + * Creates a new item with the given id. + * + * @param id the item's id + */ + StatusLineContributionItem(String id) { + super(id); + } + + /* + * @see IStatusField#setText + */ + public void setText(String text) { + fText= text; + if (fLabel != null && !fLabel.isDisposed()) { + fLabel.setText(fText); + } + } + + /* + * @see IStatusField#setImage(Image) + */ + public void setImage(Image image) { + fImage= image; + if (fLabel != null && !fLabel.isDisposed()) { + fLabel.setImage(fImage); + } + } + + /* + * @see IContributionItem#fill(Composite) + */ + public void fill(Composite parent) { + fLabel= new StatusLineLabel(parent, SWT.SHADOW_IN); + fLabel.setData(this); + + if (fText != null) + fLabel.setText(fText); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmCodeScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmCodeScanner.java new file mode 100644 index 00000000000..87d697f0e1c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmCodeScanner.java @@ -0,0 +1,243 @@ +package org.eclipse.cdt.internal.ui.editor.asm; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.internal.ui.text.AbstractCScanner; +import org.eclipse.cdt.internal.ui.text.ICColorConstants; +import org.eclipse.cdt.internal.ui.text.IColorManager; +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.WordPatternRule; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * A C code scanner. + */ +public final class AsmCodeScanner extends AbstractCScanner { + + private static class VersionedWordRule extends WordRule { + + private final String fVersion; + private final boolean fEnable; + + private String fCurrentVersion; + + public VersionedWordRule(IWordDetector detector, String version, boolean enable, String currentVersion) { + super(detector); + + fVersion= version; + fEnable= enable; + fCurrentVersion= currentVersion; + } + + public void setCurrentVersion(String version) { + fCurrentVersion= version; + } + + /* + * @see IRule#evaluate + */ + public IToken evaluate(ICharacterScanner scanner) { + IToken token= super.evaluate(scanner); + + if (fEnable) { + if (fCurrentVersion.equals(fVersion)) + return token; + + return Token.UNDEFINED; + + } else { + if (fCurrentVersion.equals(fVersion)) + return Token.UNDEFINED; + + return token; + } + } + } + + private static String[] fgKeywords= { + ".set", ".section", + ".global", + ".extern", ".macro", ".endm", + ".if", ".ifdef", ".ifndef", ".else", ".endif", + ".include", ".globl", + ".text",".data", ".rodata", ".common", ".debug", ".ctor", ".dtor", + ".asciz", ".byte", ".long", ".size", ".align", ".type" + }; + + + private static String[] fgTypes= { "char", "double", "float", "int", "long", "short", "signed", "unsigned", "void"}; + + private static String[] fgTokenProperties= { + ICColorConstants.C_KEYWORD, + ICColorConstants.C_TYPE, + ICColorConstants.C_STRING, + ICColorConstants.C_SINGLE_LINE_COMMENT, + ICColorConstants.C_DEFAULT + }; + + private VersionedWordRule fVersionedWordRule; + + /** + * Creates a C code scanner + */ + public AsmCodeScanner(IColorManager manager, IPreferenceStore store) { + super(manager, store); + initialize(); + } + + /* + * @see AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fgTokenProperties; + } + + /* + * @see AbstractCScanner#createRules() + */ + protected List createRules() { + + List rules= new ArrayList(); + + // Add rule for strings + Token token= getToken(ICColorConstants.C_SINGLE_LINE_COMMENT); + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", token)); + + // Add rule for single line comments. + rules.add(new EndOfLineRule("#", token)); + + token= getToken(ICColorConstants.C_STRING); + // Add rule for strings and character constants. + rules.add(new SingleLineRule("'", "'", token, '\\')); + rules.add(new SingleLineRule("\"", "\"", token, '\\')); + + Token other= getToken(ICColorConstants.C_DEFAULT); + + // Add generic whitespace rule. + //rules.add(new WhitespaceRule(new CWhitespaceDetector())); + + // Add word rule for labels + WordRule labelRule = new WordRule(new AsmWordDetector(false), other) { + private StringBuffer fBuffer= new StringBuffer(); + /* + * @see IRule#evaluate + */ + public IToken evaluate(ICharacterScanner scanner) { + int c= scanner.read(); + if (fDetector.isWordStart((char) c)) { + if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) { + + fBuffer.setLength(0); + do { + fBuffer.append((char) c); + c= scanner.read(); + } while (fDetector.isWordPart((char) c)); + if(c != ':') { + unreadBuffer(scanner); + return fDefaultToken; + } else { + fBuffer.append((char) c); + IToken token= (IToken) fWords.get(":"); + if (token != null) + return token; + } + + return fDefaultToken; + } + } + + scanner.unread(); + return Token.UNDEFINED; + } + /** + * Adds a word and the token to be returned if it is detected. + * + * @param word the word this rule will search for, may not be null + * @param token the token to be returned if the word has been found, may not be null + */ + public void addWord(String word, IToken token) { + + fWords.put(word, token); + } + /** + * Returns the characters in the buffer to the scanner. + * + * @param scanner the scanner to be used + */ + protected void unreadBuffer(ICharacterScanner scanner) { + for (int i= fBuffer.length() - 1; i >= 0; i--) + scanner.unread(); + } + }; + + token= getToken(ICColorConstants.C_TYPE); + labelRule.addWord(":", token); + //wordRule.setColumnConstraint(0); + rules.add(labelRule); + + // Add word rule for keywords and types + WordRule wordRule= new WordRule(new AsmWordDetector('.'), other); + for (int i=0; iTextEditor implementation of this + * IEditorPart method returns true. + */ + public boolean isSaveAsAllowed() { + return true; + } + /** + * The TextEditor implementation of this + * AbstractTextEditor method asks the user for the workspace path + * of a file resource and saves the document there. + */ + protected void performSaveAs(IProgressMonitor progressMonitor) { + /* + * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors. + * Changed Behavior to make sure that if called inside a regular save (because + * of deletion of input element) there is a way to report back to the caller. + */ + + Shell shell= getSite().getShell(); + + SaveAsDialog dialog= new SaveAsDialog(shell); + dialog.open(); + IPath path= dialog.getResult(); + + if (path == null) { + if (progressMonitor != null) + progressMonitor.setCanceled(true); + return; + } + + IWorkspace workspace= ResourcesPlugin.getWorkspace(); + IFile file= workspace.getRoot().getFile(path); + final IEditorInput newInput= new FileEditorInput(file); + + WorkspaceModifyOperation op= new WorkspaceModifyOperation() { + public void execute(final IProgressMonitor monitor) throws CoreException { + /* + * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there + * Changed false to true. + */ + getDocumentProvider().saveDocument(monitor, newInput, getDocumentProvider().getDocument(getEditorInput()), true); + } + }; + + boolean success= false; + try { + + getDocumentProvider().aboutToChange(newInput); + new ProgressMonitorDialog(shell).run(false, true, op); + success= true; + + } catch (InterruptedException x) { + } catch (InvocationTargetException x) { + // Shared with C editor + String title= CEditorMessages.getString("CEditor.error.save.title"); //$NON-NLS-1$ + String msg= MessageFormat.format(CEditorMessages.getString("CEditor.error.save.message"), new Object[] { x.getTargetException().getMessage() }); //$NON-NLS-1$ + MessageDialog.openError(shell, title, msg); + } finally { + getDocumentProvider().changed(newInput); + if (success) + setInput(newInput); + } + + if (progressMonitor != null) + progressMonitor.setCanceled(!success); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java new file mode 100644 index 00000000000..c6972d59d35 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmTextTools.java @@ -0,0 +1,129 @@ +package org.eclipse.cdt.internal.ui.editor.asm; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.util.CColorManager; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.RuleBasedPartitioner; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * This type shares all scanners and the color manager between + * its clients. + */ +public class AsmTextTools { + + private class PreferenceListener implements IPropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + adaptToPreferenceChange(event); + } + }; + /** The color manager -- use the same as for C code */ + private CColorManager fColorManager; + /** The Asm source code scanner */ + private AsmCodeScanner fCodeScanner; + /** The Asm partitions scanner */ + private AsmPartitionScanner fPartitionScanner; + + /** The preference change listener */ + private PreferenceListener fPreferenceListener= new PreferenceListener(); + + + /** + * Creates a new Asm text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public AsmTextTools(IPreferenceStore store) { + if(store == null) { + store = CPlugin.getDefault().getPreferenceStore(); + } + store.addPropertyChangeListener(fPreferenceListener); + fColorManager= new CColorManager(); + fCodeScanner= new AsmCodeScanner(fColorManager, store); + fPartitionScanner= new AsmPartitionScanner(); + } + + /** + * Creates a new Asm text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public AsmTextTools() { + this((IPreferenceStore)null); + } + /** + * Disposes all members of this tools collection. + */ + public void dispose() { + + fCodeScanner= null; + fPartitionScanner= null; + + fColorManager.dispose(); + fColorManager= null; + } + + /** + * Gets the color manager. + */ + public CColorManager getColorManager() { + return fColorManager; + } + + /** + * Gets the code scanner used. + */ + public RuleBasedScanner getCodeScanner() { + return fCodeScanner; + } + + /** + * Gets the partition scanner used. + */ + public RuleBasedScanner getPartitionScanner() { + return fPartitionScanner; + } + + /** + * Gets the document provider used. + */ + public IDocumentPartitioner createDocumentPartitioner() { + + String[] types= new String[] { + AsmPartitionScanner.C_MULTILINE_COMMENT + }; + + return new RuleBasedPartitioner(getPartitionScanner(), types); + } + + + /** + * Determines whether the preference change encoded by the given event + * changes the behavior of one its contained components. + * + * @param event the event to be investigated + * @return true if event causes a behavioral change + */ + public boolean affectsBehavior(PropertyChangeEvent event) { + return fCodeScanner.affectsBehavior(event); + } + + /** + * Adapts the behavior of the contained components to the change + * encoded in the given event. + * + * @param event the event to whch to adapt + */ + protected void adaptToPreferenceChange(PropertyChangeEvent event) { + if (fCodeScanner.affectsBehavior(event)) + fCodeScanner.adaptToPreferenceChange(event); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmWordDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmWordDetector.java new file mode 100644 index 00000000000..5410d00951b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/asm/AsmWordDetector.java @@ -0,0 +1,54 @@ +package org.eclipse.cdt.internal.ui.editor.asm; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.rules.IWordDetector; + + +/** + * A C aware word detector. + */ +public class AsmWordDetector implements IWordDetector { + private char fPrefix = 0; + private char fExtra = 0; + private boolean fStrictStart = true; + + public AsmWordDetector() { + } + + public AsmWordDetector(boolean strict) { + fStrictStart = strict; + } + + public AsmWordDetector(char extra) { + fExtra = extra; + } + + public AsmWordDetector(char prefix, char extra) { + fPrefix = prefix; + fExtra = extra; + } + /** + * @see IWordDetector#isWordIdentifierStart + */ + public boolean isWordStart(char c) { + if(fPrefix != 0) { + return (fPrefix == c); + } + if(fStrictStart) { + return (Character.isJavaIdentifierStart(c) || (c == fExtra)); + } else { + return (Character.isJavaIdentifierPart(c) || (c == fExtra)); + } + } + + /** + * @see IWordDetector#isWordIdentifierPart + */ + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeAction.java new file mode 100644 index 00000000000..32b04bd33cd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeAction.java @@ -0,0 +1,128 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.BuildAction; + +import org.eclipse.cdt.core.resources.MakeUtil; +import org.eclipse.cdt.internal.ui.CPluginImages; + + +public class MakeAction extends Action { + static final String PREFIX = "BuildAction."; + + MakeTarget[] targets; + Shell shell; + + public MakeAction (MakeTarget[] targets, Shell shell, String s) { + super (s); + this.shell = shell; + this.targets = targets; + + setToolTipText(PREFIX); + setImageDescriptor(CPluginImages.DESC_BUILD_MENU); + } + + /** + * Causes all editors to save any modified resources depending on the user's + * preference. + */ + void saveAllResources() { + + if (!BuildAction.isSaveAllSet()) + return; + + List projects = new ArrayList(); + for (int i = 0; i < targets.length; ++i ) { + MakeTarget target = targets[i]; + projects.add(target.getResource().getProject()); + } + + IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); + for (int i = 0; i < windows.length; i++) { + IWorkbenchPage [] pages = windows[i].getPages(); + for (int j = 0; j < pages.length; j++) { + IWorkbenchPage page = pages[j]; + IEditorPart[] editors = page.getEditors(); + for (int k = 0; k < editors.length; k++) { + IEditorPart editor = editors[k]; + if (editor.isDirty()) { + IEditorInput input = editor.getEditorInput(); + if (input instanceof IFileEditorInput) { + IFile inputFile = ((IFileEditorInput)input).getFile(); + if (projects.contains(inputFile.getProject())) { + page.saveEditor(editor, false); + } + } + } + } + } + } + } + + public void run() { + try { + saveAllResources(); + IRunnableWithProgress op = new IRunnableWithProgress () { + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + boolean bCleanConsole = true; + for (int i = 0; i < targets.length; ++i ) { + MakeTarget target = targets[i]; + IResource res = target.getResource(); + IProject project = res.getProject(); + MakeUtil.setSessionConsoleMode(project, bCleanConsole); + + try { + if (! project.equals(res) || target.isLeaf()) { + String dir = res.getLocation().toOSString(); + MakeUtil.setSessionBuildDir(project, dir); + if (target.isLeaf()) { + MakeUtil.setSessionTarget(project, target.toString()); + } + //System.out.println ("Build0: " + res + " " + ta); + } + //System.out.println ("Build: " + project); + project.build (IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); + } catch (CoreException e) { + } + + MakeUtil.removeSessionBuildDir(project); + MakeUtil.removeSessionTarget(project); + // Clean console only before the first target + MakeUtil.setSessionConsoleMode(project, true); + bCleanConsole = false; + } + } + }; + new ProgressMonitorDialog(shell).run(true, true, op); + } catch (InvocationTargetException e) { + // handle exception + } catch (InterruptedException e) { + // handle cancelation + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeContentProvider.java new file mode 100644 index 00000000000..3e77f31c382 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeContentProvider.java @@ -0,0 +1,168 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Control; + +public class MakeContentProvider implements ITreeContentProvider, IResourceChangeListener { + + protected Viewer viewer; + + /** + * Constructor for MakeContentProvider + */ + public MakeContentProvider() { + super(); + } + + /** + * @see ITreeContentProvider#getChildren(Object) + */ + public Object[] getChildren(Object obj) { + if (obj instanceof MakeTarget) { + MakeTarget md = (MakeTarget)obj; + return (Object[])md.getChildren(); + } + return new Object[0]; + } + + /** + * @see ITreeContentProvider#getParent(Object) + */ + public Object getParent(Object obj) { + if (obj instanceof MakeTarget) { + MakeTarget directives = (MakeTarget)obj; + return directives.getParent(); + } + return null; + } + + /** + * @see ITreeContentProvider#hasChildren(Object) + */ + public boolean hasChildren(Object obj) { + return getChildren(obj).length > 0; + } + + /** + * @see IStructuredContentProvider#getElements(Object) + */ + public Object[] getElements(Object obj) { + return getChildren(obj); + } + + /** + * @see IContentProvider#dispose() + */ + public void dispose() { + if (viewer != null) { + Object obj = viewer.getInput(); + if (obj instanceof MakeTarget) { + MakeTarget target = (MakeTarget)obj; + IWorkspace workspace = target.getResource().getWorkspace(); + workspace.removeResourceChangeListener(this); + } + } + } + + /** + * @see IContentProvider#inputChanged(Viewer, Object, Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + this.viewer = viewer; + if (oldInput != null) { + if (oldInput instanceof MakeTarget) { + IResource res = ((MakeTarget)oldInput).getResource(); + if (res instanceof IWorkspaceRoot) { + IWorkspace workspace = res.getWorkspace(); + workspace.removeResourceChangeListener(this); + } + } + } + if (newInput != null) { + if (newInput instanceof MakeTarget) { + IResource res = ((MakeTarget)newInput).getResource(); + if (res instanceof IWorkspaceRoot) { + IWorkspace workspace = res.getWorkspace(); + workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); + } + } + } + } + + public void resourceChanged (final IResourceChangeEvent event) { + final IResourceDelta deltas = event.getDelta(); + Control ctrl = viewer.getControl(); + if (ctrl != null && !ctrl.isDisposed()) { + // Get the affected resource + ctrl.getDisplay().syncExec(new Runnable() { + public void run() { + processDelta (deltas); + } + }); + } + } + + void processDelta (IResourceDelta delta) { + // Bail out if the widget was disposed. + Control ctrl = viewer.getControl(); + if (ctrl == null || ctrl.isDisposed()) { + return; + } + + if (delta == null) { + return; + } + + int changeFlags = delta.getFlags(); + + IResourceDelta[] affectedChildren = + delta.getAffectedChildren(IResourceDelta.CHANGED); + + // Not interested in Content changes. + for (int i = 0; i < affectedChildren.length; i++) { + if ((affectedChildren[i].getFlags() & IResourceDelta.TYPE) != 0) { + return; + } + } + + // handle open and closing. + if ((changeFlags & (IResourceDelta.OPEN | IResourceDelta.SYNC)) != 0) { + ctrl.setRedraw(false); + viewer.refresh(); + ctrl.setRedraw(true); + return; + } + + // Handle changed children recursively. + for (int i = 0; i < affectedChildren.length; i++) { + processDelta(affectedChildren[i]); + } + + // We are only interested in creation and deletion of folders. + affectedChildren = delta.getAffectedChildren(IResourceDelta.REMOVED | IResourceDelta.ADDED); + if (affectedChildren.length > 0) { + for (int i = 0; i < affectedChildren.length; i++) { + IResource r = affectedChildren[i].getResource(); + if (r instanceof IContainer) { + ctrl.setRedraw(false); + viewer.refresh(); + ctrl.setRedraw(true); + break; + } + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeLabelProvider.java new file mode 100644 index 00000000000..3a4c0c436be --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeLabelProvider.java @@ -0,0 +1,77 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.Hashtable; +import java.util.Map; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +public class MakeLabelProvider implements ILabelProvider { + + /** + * The cache of images that have been dispensed by this provider. + * Maps ImageDescriptor->Image. + */ + private Map imageTable = null; + + /** + * @see ILabelProvider#getImage(Object) + */ + public Image getImage(Object obj) { + Image image = null; + //obtain the cached image corresponding to the descriptor + if (imageTable == null) { + imageTable = new Hashtable(4); + } + if (obj instanceof MakeTarget) { + ImageDescriptor descriptor = ((MakeTarget)obj).getImageDescriptor(); + image = (Image) imageTable.get(descriptor); + if (image == null) { + image = descriptor.createImage(); + imageTable.put(descriptor, image); + } + } + return image; + } + + /** + * @see ILabelProvider#getText(Object) + */ + public String getText(Object obj) { + if (obj instanceof MakeTarget) { + return ((MakeTarget)obj).toString(); + } + return ""; + } + + /** + * @see IBaseLabelProvider#addListener(ILabelProviderListener) + */ + public void addListener(ILabelProviderListener arg0) { + } + + /** + * @see IBaseLabelProvider#dispose() + */ + public void dispose() { + } + + /** + * @see IBaseLabelProvider#isLabelProperty(Object, String) + */ + public boolean isLabelProperty(Object arg0, String arg1) { + return false; + } + + /** + * @see IBaseLabelProvider#removeListener(ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener arg0) { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTarget.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTarget.java new file mode 100644 index 00000000000..ade45a9b2d1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTarget.java @@ -0,0 +1,141 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.core.resources.MakeUtil; +import org.eclipse.cdt.internal.ui.CPluginImages; + + +/** + * A leaf is a IResource with a Make Directive. + * We use the term Directive instead of Make Targets + * to not confuse with remote targets. + */ + +public class MakeTarget implements IAdaptable { + + private static final MakeTarget[] emptyArray= new MakeTarget[0]; + private IResource resource; + private String target; + + public MakeTarget(IResource res) { + this(res, ""); + } + + public MakeTarget(IResource res, String goals) { + resource = res; + target = (goals == null) ? "" : goals; + } + + /** + * @see IAdaptable#getAdapter(Object) + */ + public Object getAdapter(Class adapter) { + if (adapter == IResource.class) { + return resource; + } + return null; + } + + /** + */ + public MakeTarget[] getChildren() { + if (resource != null && target.length() == 0) { + ArrayList list = new ArrayList(); + if (resource instanceof IWorkspaceRoot) { + IWorkspaceRoot root = (IWorkspaceRoot)resource; + IProject [] projects = root.getProjects(); + for (int i = 0; i < projects.length; i++) { + if (projects[i].isOpen()) { + try { + if (projects[i].hasNature(CProjectNature.C_NATURE_ID)) { + list.add (new MakeTarget(projects[i])); + } + } catch (CoreException e) { + } + } + } + } else if (resource instanceof IContainer) { + IContainer container = (IContainer)resource; + try { + IResource[] resources = container.members(); + for (int i = 0; i < resources.length; i++) { + if (resources[i] instanceof IContainer) { + list.add (new MakeTarget(resources[i])); + } + } + } catch (CoreException e) { + } + String [] targets = MakeUtil.getPersistentTargets(resource); + for (int i = 0; i < targets.length; i++) { + if (targets[i] == null) + targets[i] = ""; + list.add (new MakeTarget(resource, targets[i])); + } + } + return (MakeTarget[])list.toArray(emptyArray); + } + return emptyArray; + } + + /** + */ + public MakeTarget getParent() { + if (target.length() == 0) + return new MakeTarget(resource.getParent()); + return new MakeTarget(resource); + } + + public String toString() { + if (target.length() == 0) + return resource.getName(); + return target; + } + + public ImageDescriptor getImageDescriptor() { + if (isLeaf()) { + return CPluginImages.DESC_BUILD_MENU; + } + IWorkbenchAdapter adapter = (IWorkbenchAdapter)((IAdaptable)resource).getAdapter(IWorkbenchAdapter.class); + if (adapter == null) + return null; + return adapter.getImageDescriptor(resource); + } + + public IResource getResource () { + return resource; + } + + public boolean isLeaf () { + return (target.length() != 0); + } + + /** + * @see Object#equals(Object) + */ + public boolean equals(Object obj) { + if (null == obj) + return false; + + if (!(obj instanceof MakeTarget)) + return false; + + MakeTarget other = (MakeTarget)obj; + return (resource.equals(other.resource) && target.equals(other.target)); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTargetAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTargetAction.java new file mode 100644 index 00000000000..9672840c9c7 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeTargetAction.java @@ -0,0 +1,49 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.core.resources.MakeUtil; +import org.eclipse.cdt.internal.ui.CPluginImages; + + +public class MakeTargetAction extends Action { + + Shell shell; + IResource resource; + + public MakeTargetAction (Shell shell) { + super("Add Make Targets"); + this.shell = shell; + + setToolTipText("BuildAction"); + setImageDescriptor(CPluginImages.DESC_BUILD_MENU); + } + + public void run() { + InputDialog dialog = new InputDialog(shell, "Target Dialog: ", "Enter Target(s): ", null, null); + dialog.open(); + String value = dialog.getValue(); + if (value != null && value.length() > 0) { + if (resource != null) + MakeUtil.addPersistentTarget(resource, value); + } + } + + public void selectionChanged(IStructuredSelection selection) { + Object obj = (IAdaptable)selection.getFirstElement(); + if (obj instanceof IAdaptable) { + IAdaptable element = (IAdaptable)obj; + resource = (IResource)element.getAdapter(IResource.class); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeView.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeView.java new file mode 100644 index 00000000000..d822989bff8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/makeview/MakeView.java @@ -0,0 +1,151 @@ +package org.eclipse.cdt.internal.ui.makeview; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.part.ViewPart; + +import org.eclipse.cdt.core.resources.MakeUtil; + + +public class MakeView extends ViewPart { + + TreeViewer viewer; + + public MakeView() { + super(); + } + + /** + * @see IWorkbenchPart#setFocus() + */ + public void setFocus() { + viewer.getTree().setFocus(); + } + + /** + * Handles double clicks in viewer. + * Opens editor if file double-clicked. + */ + private void handleDoubleClick(DoubleClickEvent event) { + IStructuredSelection s = (IStructuredSelection)event.getSelection(); + Object element = s.getFirstElement(); + //System.out.println ("Double click on " + element); + if (element instanceof MakeTarget) { + MakeTarget ta = (MakeTarget)element; + Action build = new MakeAction (new MakeTarget[] {ta}, getViewSite().getShell(), "Build"); + build.run (); + } + //if (viewer.isExpandable(element)) { + // viewer.setExpandedState(element, !viewer.getExpandedState(element)); + //} + } + + /** + * called to create the context menu of the outline + */ + private void contextMenuAboutToShow(IMenuManager menu) { + IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); + Object element = selection.getFirstElement (); + if (element instanceof MakeTarget) { + final MakeTarget ta = (MakeTarget)element; + Action add = new Action ("Add") { + public void run() { + InputDialog dialog = new InputDialog(getViewSite().getShell(), + "Target Dialog: ", "Enter Target(s): ", null, null); + dialog.open (); + String value = dialog.getValue (); + if (value != null && value.length() > 0) { + IResource res = ta.getResource (); + MakeUtil.addPersistentTarget (res, value); + viewer.getControl().setRedraw(false); + viewer.refresh (); + viewer.getControl().setRedraw(true); + viewer.expandToLevel(ta, 2); + } + } + }; + Action del = new Action ("Delete") { + public void run() { + String target = ta.toString(); + if (target != null) { + IResource res = ta.getResource(); + MakeUtil.removePersistentTarget(res, target); + viewer.getControl().setRedraw(false); + viewer.refresh (); + viewer.getControl().setRedraw(true); + } + } + }; + + Action build = new MakeAction(new MakeTarget[]{ta}, getViewSite().getShell(), "Build"); + Action refresh = new Action("Refresh") { + public void run() { + viewer.refresh (); + } + }; + menu.add (add); + menu.add (del); + //menu.add (new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + menu.add (build); + menu.add (refresh); + if (ta.isLeaf()) { + add.setEnabled(false); + } else { + del.setEnabled(false); + } + } + //menu.add (new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end")); + } + + /** + * @see ContentOutlinePage#createControl + */ + public void createPartControl (Composite parent) { + + viewer= new TreeViewer (parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + viewer.setUseHashlookup (true); + viewer.setContentProvider(new MakeContentProvider()); + viewer.setLabelProvider (new MakeLabelProvider()); + + MenuManager manager= new MenuManager("#PopUp"); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + contextMenuAboutToShow(manager); + } + }); + + Control control = viewer.getControl(); + Menu menu = manager.createContextMenu(control); + control.setMenu (menu); + + viewer.setInput (new MakeTarget(ResourcesPlugin.getWorkspace().getRoot())); + + viewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + handleDoubleClick(event); + } + }); + + getSite().setSelectionProvider(viewer); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java new file mode 100644 index 00000000000..ac27d12ad0b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java @@ -0,0 +1,931 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.texteditor.WorkbenchChainedTextFontFieldEditor; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.ContentAssistPreference; +import org.eclipse.cdt.internal.ui.text.ICColorConstants; +import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; + + +/* + * The page for setting the editor options. + */ +public class CEditorPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + public final OverlayPreferenceStore.OverlayKey[] fKeys= new OverlayPreferenceStore.OverlayKey[] { + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.PREFERENCE_COLOR_FOREGROUND), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.PREFERENCE_COLOR_BACKGROUND), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_MULTI_LINE_COMMENT), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_MULTI_LINE_COMMENT + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_SINGLE_LINE_COMMENT), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_SINGLE_LINE_COMMENT + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_KEYWORD), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_KEYWORD + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_TYPE), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_TYPE + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_STRING), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_STRING + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_DEFAULT), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_DEFAULT + "_bold"), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.MATCHING_BRACKETS_COLOR), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS_NOBOX), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.CURRENT_LINE_COLOR), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.CURRENT_LINE), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.PROBLEM_INDICATION_COLOR), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.PROBLEM_INDICATION), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.SPACES_FOR_TABS), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.PRINT_MARGIN_COLOR), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, CEditor.PRINT_MARGIN_COLUMN), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.PRINT_MARGIN), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.LINKED_POSITION_COLOR), + + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.AUTOACTIVATION), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.INT, ContentAssistPreference.AUTOACTIVATION_DELAY), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.AUTOINSERT), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PROPOSALS_BACKGROUND), + //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PROPOSALS_FOREGROUND), + //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PARAMETERS_BACKGROUND), + //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.PARAMETERS_FOREGROUND), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_C), + //new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_JAVADOC), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.SHOW_DOCUMENTED_PROPOSALS), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ORDER_PROPOSALS), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.CASE_SENSITIVITY), + new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ContentAssistPreference.ADD_INCLUDE) + + }; + + private final String[][] fListModel= new String[][] { + { "Multi-line comment", ICColorConstants.C_MULTI_LINE_COMMENT }, + { "Single-line comment", ICColorConstants.C_SINGLE_LINE_COMMENT }, + { "Keywords", ICColorConstants.C_KEYWORD }, + { "Built-in types", ICColorConstants.C_TYPE }, + { "Strings", ICColorConstants.C_STRING }, + { "Others", ICColorConstants.C_DEFAULT } + }; + + private OverlayPreferenceStore fOverlayStore; + private CTextTools fCTextTools; + + private Map fColorButtons= new HashMap(); + private SelectionListener fColorButtonListener= new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + ColorEditor editor= (ColorEditor) e.widget.getData(); + PreferenceConverter.setValue(fOverlayStore, (String) fColorButtons.get(editor), editor.getColorValue()); + } + }; + + private Map fCheckBoxes= new HashMap(); + private SelectionListener fCheckBoxListener= new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + public void widgetSelected(SelectionEvent e) { + Button button= (Button) e.widget; + fOverlayStore.setValue((String) fCheckBoxes.get(button), button.getSelection()); + } + }; + + private Map fTextFields= new HashMap(); + private ModifyListener fTextFieldListener= new ModifyListener() { + public void modifyText(ModifyEvent e) { + Text text= (Text) e.widget; + fOverlayStore.setValue((String) fTextFields.get(text), text.getText()); + } + }; + + private WorkbenchChainedTextFontFieldEditor fFontEditor; + private List fList; + private ColorEditor fForegroundColorEditor; + private ColorEditor fBackgroundColorEditor; + private Button fBackgroundDefaultRadioButton; + private Button fBackgroundCustomRadioButton; + private Button fBackgroundColorButton; + private Button fBoldCheckBox; + private SourceViewer fPreviewViewer; + + public CEditorPreferencePage() { + setDescription(CPlugin.getResourceString("CEditorPreferencePage.description")); + setPreferenceStore(CPlugin.getDefault().getPreferenceStore()); + fOverlayStore= new OverlayPreferenceStore(getPreferenceStore(), fKeys); + } + + public static void initDefaults(IPreferenceStore store) { + + Color color; + Display display= Display.getDefault(); + + store.setDefault(CEditor.MATCHING_BRACKETS, true); + store.setDefault(CEditor.MATCHING_BRACKETS_NOBOX, false); + color= display.getSystemColor(SWT.COLOR_GRAY); + PreferenceConverter.setDefault(store, CEditor.MATCHING_BRACKETS_COLOR, color.getRGB()); + + store.setDefault(CEditor.CURRENT_LINE, true); + PreferenceConverter.setDefault(store, CEditor.CURRENT_LINE_COLOR, new RGB(225, 235, 224)); + + store.setDefault(CEditor.PRINT_MARGIN, true); + store.setDefault(CEditor.PRINT_MARGIN_COLUMN, 80); + PreferenceConverter.setDefault(store, CEditor.PRINT_MARGIN_COLOR, new RGB(176, 180 , 185)); + + //PreferenceConverter.setDefault(store, CEditor.PREFERENCE_COLOR_FIND_SCOPE, new RGB(185, 176 , 180)); + + store.setDefault(CEditor.PROBLEM_INDICATION, true); + PreferenceConverter.setDefault(store, CEditor.PROBLEM_INDICATION_COLOR, new RGB(255, 0 , 128)); + + //store.setDefault(CompilationUnitEditor.OVERVIEW_RULER, false); + + WorkbenchChainedTextFontFieldEditor.startPropagate(store, JFaceResources.TEXT_FONT); + + color= display.getSystemColor(SWT.COLOR_LIST_FOREGROUND); + PreferenceConverter.setDefault(store, CEditor.PREFERENCE_COLOR_FOREGROUND, color.getRGB()); + store.setDefault(CEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT, true); + + color= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND); + PreferenceConverter.setDefault(store, CEditor.PREFERENCE_COLOR_BACKGROUND, color.getRGB()); + store.setDefault(CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT, false); + + store.setDefault(CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH, 4); + + store.setDefault(CEditor.SPACES_FOR_TABS, false); + + PreferenceConverter.setDefault(store, ICColorConstants.C_MULTI_LINE_COMMENT, new RGB(63, 127, 95)); + store.setDefault(ICColorConstants.C_MULTI_LINE_COMMENT + "_bold", false); + + PreferenceConverter.setDefault(store, ICColorConstants.C_SINGLE_LINE_COMMENT, new RGB(63, 125, 95)); + store.setDefault(ICColorConstants.C_SINGLE_LINE_COMMENT + "_bold", false); + + PreferenceConverter.setDefault(store, ICColorConstants.C_KEYWORD, new RGB(127, 0, 85)); + store.setDefault(ICColorConstants.C_KEYWORD + "_bold", true); + + PreferenceConverter.setDefault(store, ICColorConstants.C_TYPE, new RGB(127, 0, 85)); + store.setDefault(ICColorConstants.C_TYPE + "_bold", true); + + PreferenceConverter.setDefault(store, ICColorConstants.C_STRING, new RGB(42, 0, 255)); + store.setDefault(ICColorConstants.C_STRING + "_bold", false); + + PreferenceConverter.setDefault(store, ICColorConstants.C_DEFAULT, new RGB(0, 0, 0)); + store.setDefault(ICColorConstants.C_DEFAULT + "_bold", false); + + + PreferenceConverter.setDefault(store, CEditor.LINKED_POSITION_COLOR, new RGB(0, 200 , 100)); + + store.setDefault(ContentAssistPreference.AUTOACTIVATION, false); + store.setDefault(ContentAssistPreference.AUTOACTIVATION_DELAY, 500); + + store.setDefault(ContentAssistPreference.AUTOINSERT, true); + PreferenceConverter.setDefault(store, ContentAssistPreference.PROPOSALS_BACKGROUND, new RGB(254, 241, 233)); + //PreferenceConverter.setDefault(store, ContentAssistPreference.PROPOSALS_FOREGROUND, new RGB(0, 0, 0)); + //PreferenceConverter.setDefault(store, ContentAssistPreference.PARAMETERS_BACKGROUND, new RGB(254, 241, 233)); + //PreferenceConverter.setDefault(store, ContentAssistPreference.PARAMETERS_FOREGROUND, new RGB(0, 0, 0)); + //store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_C, ".,"); + //store.setDefault(ContentAssistPreference.AUTOACTIVATION_TRIGGERS_JAVADOC, "@"); + //store.setDefault(ContentAssistPreference.SHOW_VISIBLE_PROPOSALS, true); + store.setDefault(ContentAssistPreference.CASE_SENSITIVITY, false); + store.setDefault(ContentAssistPreference.ORDER_PROPOSALS, false); + store.setDefault(ContentAssistPreference.ADD_INCLUDE, true); + + } + + /* + * @see IWorkbenchPreferencePage#init() + */ + public void init(IWorkbench workbench) { + } + + /* + * @see PreferencePage#createControl(Composite) + */ + public void createControl(Composite parent) { + super.createControl(parent); + //WorkbenchHelp.setHelp(getControl(), ICHelpContextIds.JAVA_EDITOR_PREFERENCE_PAGE); + } + + private void handleListSelection() { + int i= fList.getSelectionIndex(); + String key= fListModel[i][1]; + RGB rgb= PreferenceConverter.getColor(fOverlayStore, key); + fForegroundColorEditor.setColorValue(rgb); + fBoldCheckBox.setSelection(fOverlayStore.getBoolean(key + "_bold")); + } + + private Control createColorPage(Composite parent) { + + Composite colorComposite= new Composite(parent, SWT.NULL); + colorComposite.setLayout(new GridLayout()); + + Composite backgroundComposite= new Composite(colorComposite, SWT.NULL); + GridLayout layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + backgroundComposite.setLayout(layout); + + Label label= new Label(backgroundComposite, SWT.NULL); + label.setText("Bac&kground Color:"); + GridData gd= new GridData(); + gd.horizontalSpan= 2; + label.setLayoutData(gd); + + SelectionListener backgroundSelectionListener= new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + boolean custom= fBackgroundCustomRadioButton.getSelection(); + fBackgroundColorButton.setEnabled(custom); + fOverlayStore.setValue(CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT, !custom); + } + public void widgetDefaultSelected(SelectionEvent e) {} + }; + + fBackgroundDefaultRadioButton= new Button(backgroundComposite, SWT.RADIO | SWT.LEFT); + fBackgroundDefaultRadioButton.setText("S&ystem Default"); + gd= new GridData(); + gd.horizontalSpan= 2; + fBackgroundDefaultRadioButton.setLayoutData(gd); + fBackgroundDefaultRadioButton.addSelectionListener(backgroundSelectionListener); + + fBackgroundCustomRadioButton= new Button(backgroundComposite, SWT.RADIO | SWT.LEFT); + fBackgroundCustomRadioButton.setText("C&ustom"); + fBackgroundCustomRadioButton.addSelectionListener(backgroundSelectionListener); + + fBackgroundColorEditor= new ColorEditor(backgroundComposite); + fBackgroundColorButton= fBackgroundColorEditor.getButton(); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment= GridData.BEGINNING; + fBackgroundColorButton.setLayoutData(gd); + + label= new Label(colorComposite, SWT.LEFT); + label.setText("Fo®round:"); + label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Composite editorComposite= new Composite(colorComposite, SWT.NULL); + layout= new GridLayout(); + layout.numColumns= 2; + layout.marginHeight= 0; + layout.marginWidth= 0; + editorComposite.setLayout(layout); + gd= new GridData(GridData.FILL_BOTH); + editorComposite.setLayoutData(gd); + + fList= new List(editorComposite, SWT.SINGLE | SWT.V_SCROLL); + gd= new GridData(GridData.FILL_BOTH); + gd.heightHint= convertHeightInCharsToPixels(5); + fList.setLayoutData(gd); + + Composite stylesComposite= new Composite(editorComposite, SWT.NULL); + layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.numColumns= 2; + stylesComposite.setLayout(layout); + stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + label= new Label(stylesComposite, SWT.LEFT); + label.setText("C&olor:"); + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label.setLayoutData(gd); + + fForegroundColorEditor= new ColorEditor(stylesComposite); + Button foregroundColorButton= fForegroundColorEditor.getButton(); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment= GridData.BEGINNING; + foregroundColorButton.setLayoutData(gd); + + label= new Label(stylesComposite, SWT.LEFT); + label.setText("&Bold:"); + gd= new GridData(); + gd.horizontalAlignment= GridData.BEGINNING; + label.setLayoutData(gd); + + fBoldCheckBox= new Button(stylesComposite, SWT.CHECK); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalAlignment= GridData.BEGINNING; + fBoldCheckBox.setLayoutData(gd); + + label= new Label(colorComposite, SWT.LEFT); + label.setText("Preview:"); + label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Control previewer= createPreviewer(colorComposite); + gd= new GridData(GridData.FILL_BOTH); + gd.widthHint= convertWidthInCharsToPixels(80); + gd.heightHint= convertHeightInCharsToPixels(15); + previewer.setLayoutData(gd); + + + fList.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + public void widgetSelected(SelectionEvent e) { + handleListSelection(); + } + }); + + foregroundColorButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + public void widgetSelected(SelectionEvent e) { + int i= fList.getSelectionIndex(); + String key= fListModel[i][1]; + + PreferenceConverter.setValue(fOverlayStore, key, fForegroundColorEditor.getColorValue()); + } + }); + + fBackgroundColorButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + public void widgetSelected(SelectionEvent e) { + PreferenceConverter.setValue(fOverlayStore, CEditor.PREFERENCE_COLOR_BACKGROUND, fBackgroundColorEditor.getColorValue()); + } + }); + + fBoldCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + // do nothing + } + public void widgetSelected(SelectionEvent e) { + int i= fList.getSelectionIndex(); + String key= fListModel[i][1]; + fOverlayStore.setValue(key + "_bold", fBoldCheckBox.getSelection()); + } + }); + + return colorComposite; + } + + private Control createPreviewer(Composite parent) { + + fCTextTools= new CTextTools(fOverlayStore); + + fPreviewViewer= new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL); + fPreviewViewer.configure(new CSourceViewerConfiguration(fCTextTools, null)); + fPreviewViewer.getTextWidget().setFont(JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT)); + fPreviewViewer.setEditable(false); + + initializeViewerColors(fPreviewViewer); + + String content= loadPreviewContentFromFile("ColorSettingPreviewCode.txt"); + IDocument document= new Document(content); + IDocumentPartitioner partitioner= fCTextTools.createDocumentPartitioner(); + partitioner.connect(document); + document.setDocumentPartitioner(partitioner); + + fPreviewViewer.setDocument(document); + + fOverlayStore.addPropertyChangeListener(new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + String p= event.getProperty(); + if (p.equals(CEditor.PREFERENCE_COLOR_BACKGROUND) || + p.equals(CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) + { + initializeViewerColors(fPreviewViewer); + } + + fPreviewViewer.getDocument().set(fPreviewViewer.getDocument().get()); + //fPreviewViewer.refresh(); + } + }); + + return fPreviewViewer.getControl(); + } + + private Color fBackgroundColor; + + /** + * Initializes the given viewer's colors. + * + * @param viewer the viewer to be initialized + */ + private void initializeViewerColors(ISourceViewer viewer) { + + IPreferenceStore store= fOverlayStore; + if (store != null) { + + StyledText styledText= viewer.getTextWidget(); + + // ---------- background color ---------------------- + Color color= store.getBoolean(CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT) + ? null + : createColor(store, CEditor.PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay()); + styledText.setBackground(color); + + if (fBackgroundColor != null) + fBackgroundColor.dispose(); + + fBackgroundColor= color; + } + } + + /** + * Creates a color from the information stored in the given preference store. + * Returns null if there is no such information available. + */ + private Color createColor(IPreferenceStore store, String key, Display display) { + + RGB rgb= null; + + if (store.contains(key)) { + + if (store.isDefault(key)) + rgb= PreferenceConverter.getDefaultColor(store, key); + else + rgb= PreferenceConverter.getColor(store, key); + + if (rgb != null) + return new Color(display, rgb); + } + + return null; + } + + // sets enabled flag for a control and all its sub-tree + private static void setEnabled(Control control, boolean enable) { + control.setEnabled(enable); + if (control instanceof Composite) { + Composite composite= (Composite) control; + Control[] children= composite.getChildren(); + for (int i= 0; i < children.length; i++) + setEnabled(children[i], enable); + } + } + + + private Button fBracketHighlightButton; + private Button fBracketHighlightBoxButton; + private Control fBracketHighlightColor; + private Button fLineHighlightButton; + private Control fLineHighlightColor; + private Button fPrintMarginButton; + private Control fPrintMarginColor; + private Control fPrintMarginColumn; + private Button fProblemIndicationButton; + private Control fProblemIndicationColor; + private Control fFindScopeColor; + private Control fLinkedPositionColor; + + private Control createBehaviorPage(Composite parent) { + + Composite behaviorComposite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); layout.numColumns= 2; + behaviorComposite.setLayout(layout); + + + String label= "Text &font:"; + addTextFontEditor(behaviorComposite, label, CEditor.PREFERENCE_FONT); + + label= "Displayed &tab width:"; + addTextField(behaviorComposite, label, CSourceViewerConfiguration.PREFERENCE_TAB_WIDTH, 2, 0); + + label= "Insert &space for tabs"; + addCheckBox(behaviorComposite, label, CEditor.SPACES_FOR_TABS, 0); + + //label= "Show overview &ruler"; + //addCheckBox(behaviorComposite, label, CompilationUnitEditor.OVERVIEW_RULER, 0); + + label= "Highlight &matching brackets"; + fBracketHighlightButton= addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS, 0); + + label= "Only c&olor bracket text"; + fBracketHighlightBoxButton= addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS_NOBOX, 0); + + label= "Matching &brackets highlight color:"; + fBracketHighlightColor= addColorButton(behaviorComposite, label, CEditor.MATCHING_BRACKETS_COLOR, 0); + + fBracketHighlightButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + setEnabled(fBracketHighlightColor, fBracketHighlightButton.getSelection()); + setEnabled(fBracketHighlightBoxButton, fBracketHighlightButton.getSelection()); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + + + label= "Highlight ¤t line"; + fLineHighlightButton= addCheckBox(behaviorComposite, label, CEditor.CURRENT_LINE, 0); + + label= "Current &line highlight color:"; + fLineHighlightColor= addColorButton(behaviorComposite, label, CEditor.CURRENT_LINE_COLOR, 0); + + fLineHighlightButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + setEnabled(fLineHighlightColor, fLineHighlightButton.getSelection()); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + + label= "Highlight &problems"; + fProblemIndicationButton= addCheckBox(behaviorComposite, label, CEditor.PROBLEM_INDICATION, 0); + + label= "Prob&lem highlight color:"; + fProblemIndicationColor= addColorButton(behaviorComposite, label, CEditor.PROBLEM_INDICATION_COLOR, 0); + + fProblemIndicationButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + setEnabled(fProblemIndicationColor, fProblemIndicationButton.getSelection()); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + + label= "Show print &margin"; + fPrintMarginButton= addCheckBox(behaviorComposite, label, CEditor.PRINT_MARGIN, 0); + + label= "Print m&argin color:"; + fPrintMarginColor= addColorButton(behaviorComposite, label, CEditor.PRINT_MARGIN_COLOR, 0); + + label= "Print margin col&umn:"; + fPrintMarginColumn= addTextField(behaviorComposite, label, CEditor.PRINT_MARGIN_COLUMN, 4, 0); + + fPrintMarginButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + boolean enabled= fPrintMarginButton.getSelection(); + setEnabled(fPrintMarginColor, enabled); + setEnabled(fPrintMarginColumn, enabled); + } + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + + //label= "F&ind Scope:"; + //fFindScopeColor= addColorButton(behaviorComposite, label, CEditor.PREFERENCE_COLOR_FIND_SCOPE, 0); + label= "Lin&ked position color:"; //$NON-NLS-1$ + fLinkedPositionColor= addColorButton(behaviorComposite, label, CEditor.LINKED_POSITION_COLOR, 0); + + return behaviorComposite; + } + + private Control createContentAssistPage(Composite parent) { + + Composite contentAssistComposite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); layout.numColumns= 2; + contentAssistComposite.setLayout(layout); + + String label= "Insert single &proposals automatically"; + addCheckBox(contentAssistComposite, label, ContentAssistPreference.AUTOINSERT, 0); + + //label= "Show only proposals visible in the invocation conte&xt"; + //addCheckBox(contentAssistComposite, label, ContentAssistPreference.SHOW_VISIBLE_PROPOSALS, 0); + + //label= "Show only proposals with &matching cases"; + //addCheckBox(contentAssistComposite, label, ContentAssistPreference.CASE_SENSITIVITY, 0); + + //label= "Present proposals in a&lphabetical order"; + //addCheckBox(contentAssistComposite, label, ContentAssistPreference.ORDER_PROPOSALS, 0); + + label= "&Enable auto activation"; + addCheckBox(contentAssistComposite, label, ContentAssistPreference.AUTOACTIVATION, 0); + + //label= "Automatically add &include for proposals from system functions"; + //addCheckBox(contentAssistComposite, label, ContentAssistPreference.ADD_INCLUDE, 0); + + label= "Auto activation dela&y:"; + addTextField(contentAssistComposite, label, ContentAssistPreference.AUTOACTIVATION_DELAY, 4, 0); + + label= "Auto activation &triggers for C:"; + addTextField(contentAssistComposite, label, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_C, 25, 0); + + //label= "Auto activation triggers for &JavaDoc:"; + //addTextField(contentAssistComposite, label, ContentAssistPreference.AUTOACTIVATION_TRIGGERS_JAVADOC, 25, 0); + + label= "&Background for completion proposals:"; + addColorButton(contentAssistComposite, label, ContentAssistPreference.PROPOSALS_BACKGROUND, 0); + + //label= "&Foreground for completion proposals:"; + //addColorButton(contentAssistComposite, label, ContentAssistPreference.PROPOSALS_FOREGROUND, 0); + + //label= "Bac&kground for method parameters:"; + //addColorButton(contentAssistComposite, label, ContentAssistPreference.PARAMETERS_BACKGROUND, 0); + + //label= "Fo®round for method parameters:"; + //addColorButton(contentAssistComposite, label, ContentAssistPreference.PARAMETERS_FOREGROUND, 0); + + return contentAssistComposite; + } + + /* + * @see PreferencePage#createContents(Composite) + */ + protected Control createContents(Composite parent) { + + fOverlayStore.load(); + fOverlayStore.start(); + + TabFolder folder= new TabFolder(parent, SWT.NONE); + folder.setLayout(new TabFolderLayout()); + folder.setLayoutData(new GridData(GridData.FILL_BOTH)); + + TabItem item= new TabItem(folder, SWT.NONE); + item.setText("&General"); + item.setImage(CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT)); + item.setControl(createBehaviorPage(folder)); + + item= new TabItem(folder, SWT.NONE); + item.setText("&Colors"); + item.setImage(CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT)); + item.setControl(createColorPage(folder)); + + item= new TabItem(folder, SWT.NONE); + item.setText("Code A&ssist"); + item.setImage(CPluginImages.get(CPluginImages.IMG_OBJS_TUNIT)); + item.setControl(createContentAssistPage(folder)); + + initialize(); + + return folder; + } + + private void initialize() { + + fFontEditor.setPreferenceStore(getPreferenceStore()); + fFontEditor.setPreferencePage(this); + fFontEditor.load(); + + initializeFields(); + + for (int i= 0; i < fListModel.length; i++) + fList.add(fListModel[i][0]); + + fList.getDisplay().asyncExec(new Runnable() { + public void run() { + fList.select(0); + handleListSelection(); + } + }); + } + + private void initializeFields() { + + Iterator e= fColorButtons.keySet().iterator(); + while (e.hasNext()) { + ColorEditor c= (ColorEditor) e.next(); + String key= (String) fColorButtons.get(c); + RGB rgb= PreferenceConverter.getColor(fOverlayStore, key); + c.setColorValue(rgb); + } + + e= fCheckBoxes.keySet().iterator(); + while (e.hasNext()) { + Button b= (Button) e.next(); + String key= (String) fCheckBoxes.get(b); + b.setSelection(fOverlayStore.getBoolean(key)); + } + + e= fTextFields.keySet().iterator(); + while (e.hasNext()) { + Text t= (Text) e.next(); + String key= (String) fTextFields.get(t); + t.setText(fOverlayStore.getString(key)); + } + + RGB rgb= PreferenceConverter.getColor(fOverlayStore, CEditor.PREFERENCE_COLOR_BACKGROUND); + fBackgroundColorEditor.setColorValue(rgb); + + boolean default_= fOverlayStore.getBoolean(CEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT); + fBackgroundDefaultRadioButton.setSelection(default_); + fBackgroundCustomRadioButton.setSelection(!default_); + fBackgroundColorButton.setEnabled(!default_); + + setEnabled(fBracketHighlightColor, fBracketHighlightButton.getSelection()); + setEnabled(fLineHighlightColor, fLineHighlightButton.getSelection()); + } + + /* + * @see PreferencePage#performOk() + */ + public boolean performOk() { + fFontEditor.store(); + fOverlayStore.propagate(); + return true; + } + + /* + * @see PreferencePage#performDefaults() + */ + protected void performDefaults() { + + fFontEditor.loadDefault(); + + fOverlayStore.loadDefaults(); + initializeFields(); + handleListSelection(); + + super.performDefaults(); + + //fPreviewViewer.invalidateTextPresentation(); + } + + /* + * @see DialogPage#dispose() + */ + public void dispose() { + + if (fCTextTools != null) { + fCTextTools= null; + } + + fFontEditor.setPreferencePage(null); + fFontEditor.setPreferenceStore(null); + + if (fOverlayStore != null) { + fOverlayStore.stop(); + fOverlayStore= null; + } + + super.dispose(); + } + + private Control addColorButton(Composite parent, String label, String key, int indentation) { + + Composite composite= new Composite(parent, SWT.NONE); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan= 2; + composite.setLayoutData(gd); + + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + + Label labelControl= new Label(composite, SWT.NONE); + labelControl.setText(label); + + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalIndent= indentation; + labelControl.setLayoutData(gd); + + ColorEditor editor= new ColorEditor(composite); + Button button= editor.getButton(); + button.setData(editor); + + gd= new GridData(); + gd.horizontalAlignment= GridData.END; + button.setLayoutData(gd); + button.addSelectionListener(fColorButtonListener); + + fColorButtons.put(editor, key); + + return composite; + } + + private Button addCheckBox(Composite parent, String label, String key, int indentation) { + Button checkBox= new Button(parent, SWT.CHECK); + checkBox.setText(label); + + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalIndent= indentation; + gd.horizontalSpan= 2; + checkBox.setLayoutData(gd); + checkBox.addSelectionListener(fCheckBoxListener); + + fCheckBoxes.put(checkBox, key); + + return checkBox; + } + + private Control addTextField(Composite parent, String label, String key, int textLimit, int indentation) { + + Composite composite= new Composite(parent, SWT.NONE); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan= 2; + composite.setLayoutData(gd); + + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + + Label labelControl= new Label(composite, SWT.NONE); + labelControl.setText(label); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalIndent= indentation; + labelControl.setLayoutData(gd); + + Text textControl= new Text(composite, SWT.BORDER | SWT.SINGLE); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint= convertWidthInCharsToPixels(textLimit + 1); + gd.horizontalAlignment= GridData.END; + textControl.setLayoutData(gd); + textControl.setTextLimit(textLimit); + textControl.addModifyListener(fTextFieldListener); + fTextFields.put(textControl, key); + + return composite; + } + + private void addTextFontEditor(Composite parent, String label, String key) { + + Composite editorComposite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); + layout.numColumns= 3; + editorComposite.setLayout(layout); + fFontEditor= new WorkbenchChainedTextFontFieldEditor(key, label, editorComposite); + fFontEditor.setChangeButtonText("C&hange..."); + + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan= 2; + editorComposite.setLayoutData(gd); + } + + private String loadPreviewContentFromFile(String filename) { + String line; + String separator= System.getProperty("line.separator"); //$NON-NLS-1$ + StringBuffer buffer= new StringBuffer(512); + BufferedReader reader= null; + try { + reader= new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(filename))); + while ((line= reader.readLine()) != null) { + buffer.append(line); + buffer.append(separator); + } + } catch (IOException io) { + CPlugin.log(io); + } finally { + if (reader != null) { + try { reader.close(); } catch (IOException e) {} + } + } + return buffer.toString(); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CLaunchingPropertyPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CLaunchingPropertyPage.java new file mode 100644 index 00000000000..4bfa92df3d5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CLaunchingPropertyPage.java @@ -0,0 +1,222 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.QualifiedName; + +import org.eclipse.jface.dialogs.ErrorDialog; + +import org.eclipse.ui.dialogs.PropertyPage; +import org.eclipse.ui.help.DialogPageContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.dialogs.StatusTool; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringButtonDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; +import org.eclipse.cdt.internal.ui.wizards.swt.MGridLayout; + +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +public class CLaunchingPropertyPage extends PropertyPage { + + private static final String PAGE_NAME= "CLaunchingPropertyPage"; + private static final String ARGUMENTS= PAGE_NAME + ".arguments"; + private static final String WORKINGDIR= PAGE_NAME + ".workingdir"; + + private static final String NO_CPROJECT= PAGE_NAME + ".nocproject.label"; + + private static final String ERROR_WORKINGDIR_NOTEXISTS= PAGE_NAME + ".error.WorkingDirNotExists"; + + private StringDialogField fArgumentField; + private StringButtonDialogField fWorkingDirField; + + private StatusInfo fWorkingDirStatus; + + private QualifiedName fArgumentsPropertyName; + private QualifiedName fWorkingDirPropertyName; + + private Shell fShell; + + public CLaunchingPropertyPage() { + LaunchingDialogFieldsAdapter adapter= new LaunchingDialogFieldsAdapter(); + + fArgumentField= new StringDialogField(); + fArgumentField.setLabelText(CPlugin.getResourceString(ARGUMENTS + ".label")); + fArgumentField.setDialogFieldListener(adapter); + + fWorkingDirField= new StringButtonDialogField(adapter); + fWorkingDirField.setLabelText(CPlugin.getResourceString(WORKINGDIR + ".label")); + fWorkingDirField.setButtonLabel(CPlugin.getResourceString(WORKINGDIR + ".browse")); + fWorkingDirField.setDialogFieldListener(adapter); + + fWorkingDirStatus= new StatusInfo(); + + fArgumentsPropertyName= new QualifiedName(CPlugin.PLUGIN_ID, "arguments"); + fWorkingDirPropertyName= new QualifiedName(CPlugin.PLUGIN_ID, "workingdir"); + } + + /** + * @see PreferencePage#createContents(Composite) + */ + protected Control createContents(Composite parent) { + Composite composite= new Composite(parent, SWT.NONE); + fShell= parent.getShell(); + + MGridLayout layout= new MGridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 0; + layout.minimumWidth= 400; + layout.minimumHeight= 350; + layout.numColumns= 3; + composite.setLayout(layout); + + boolean isCProject= false; + try { + IFile file= getInputFile(); + isCProject= (file.getProject().hasNature(CProjectNature.C_NATURE_ID)); + } catch (CoreException e) { + CPlugin.log(e); + } + + if (isCProject) { + fArgumentField.doFillIntoGrid(composite, 3); + fWorkingDirField.doFillIntoGrid(composite, 3); + initialize(); + } else { + DialogField labelField= new DialogField(); + labelField.setLabelText(CPlugin.getResourceString(NO_CPROJECT)); + labelField.doFillIntoGrid(composite, 3); + } + WorkbenchHelp.setHelp(parent, new DialogPageContextComputer(this, ICHelpContextIds.LAUNCH_PROPERTY_PAGE)); + + return composite; + } + + + private void initialize() { + IFile file= getInputFile(); + if (file != null) { + try { + String arguments= file.getPersistentProperty(fArgumentsPropertyName); + if (arguments != null) { + fArgumentField.setText(arguments); + } + + String workingdir= file.getPersistentProperty(fWorkingDirPropertyName); + if (workingdir != null) { + fWorkingDirField.setText(workingdir); + } else { + fWorkingDirField.setText(file.getParent().getLocation().toOSString()); + } + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + } + } + } + + /** + * @see PreferencePage#performOk + */ + public boolean performOk() { + IFile file= getInputFile(); + if (file != null) { + try { + file.setPersistentProperty(fArgumentsPropertyName, fArgumentField.getText()); + file.setPersistentProperty(fWorkingDirPropertyName, fWorkingDirField.getText()); + } catch (CoreException e) { + ErrorDialog.openError(fShell, "Error", null, e.getStatus()); + CPlugin.log(e.getStatus()); + return false; + } + } + return true; + } + + /** + * @see PreferencePage#doDefaults + */ + protected void performDefaults() { + initialize(); + super.performDefaults(); + } + + private class LaunchingDialogFieldsAdapter implements IDialogFieldListener, IStringButtonAdapter { + + public void changeControlPressed(DialogField field) { + String oldValue= fWorkingDirField.getText(); + String newValue= chooseFolder(oldValue); + if (newValue != null) { + fWorkingDirField.setText(newValue); + } + } + + public void dialogFieldChanged(DialogField field) { + doFieldChanged(field); + } + } + + private void doFieldChanged(DialogField field) { + if (field == fWorkingDirField) { + updateWorkingDirStatus(); + } + projectStatusChanged(fWorkingDirStatus); + } + + + private void updateWorkingDirStatus() { + String str= fWorkingDirField.getText(); + if (!"".equals(str)) { + IPath path= new Path(str); + if (!path.toFile().isDirectory()) { + fWorkingDirStatus.setError(CPlugin.getResourceString(ERROR_WORKINGDIR_NOTEXISTS)); + return; + } + } + fWorkingDirStatus.setOK(); + } + + private IFile getInputFile() { + return (IFile)getElement(); + } + + private String chooseFolder(String initPath) { + DirectoryDialog dialog= new DirectoryDialog(fShell, 0); + dialog.setFilterPath(initPath); + String res= dialog.open(); + return res; + } + + public void projectStatusChanged(IStatus status) { + setValid(!status.matches(IStatus.ERROR)); + StatusTool.applyToStatusLine(this, status); + } + + /** + * @see DialogPage#setVisible(boolean) + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible && fShell != null) { + fArgumentField.postSetFocusOnDialogField(fShell.getDisplay()); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java new file mode 100644 index 00000000000..fb6b2eadd6c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java @@ -0,0 +1,163 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.FontFieldEditor; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.JFaceResources; + +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.help.DialogPageContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; + +/** + * The page for setting c plugin preferences. + */ +public class CPluginPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { + + public static final String PREF_CONSOLE_FONT= "consoleFont"; + + private static final String PREF_BUILD_LOCATION= "buildLocation"; + private static final String PREF_STOP_ON_ERROR= "stopOnError"; + private static final String PREF_CLEAR_CONSOLE= "clearConsole"; + private static final String PREF_CONSOLE_ON_TOP= "consoleOnTop"; + private static final String PREF_AUTO_OPEN_CONSOLE = "autoOpenConsole"; + private static final String PREF_LINK_TO_EDITOR= "linkToEditor"; + public static final String SHOW_CU_CHILDREN="CUChildren"; //$NON-NLS-1$ + + private static final String PAGE_DESC= "CBasePreferencePage.description"; + private static final String BUILD_LOC_LABEL= "CBasePreferencePage.buildLocation.label"; + private static final String CLEAR_CONSOLE_LABEL= "CBasePreferencePage.clearConsole.label"; + private static final String CONSOLE_ON_TOP_LABEL= "CBasePreferencePage.consoleOnTop.label"; + private static final String AUTO_OPEN_CONSOLE_LABEL= "CBasePreferencePage.autoOpenConsole.label"; + private static final String LINK_TO_EDITOR_LABEL= "CBasePreferencePage.linkToEditor.label"; + private static final String SHOW_CU_CHILDREN_LABEL= "CBasePreferencePage.CUChildren.label"; + //private static final String EDITOR_FONT_LABEL= "CBasePreferencePage.editorFont.label"; + private static final String CONSOLE_FONT_LABEL= "CBasePreferencePage.consoleFont.label"; + + public CPluginPreferencePage() { + super(GRID); + setPreferenceStore(CPlugin.getDefault().getPreferenceStore()); + } + + /** + * @see PreferencePage#createControl(Composite) + */ + public void createControl(Composite parent) { + super.createControl(parent); + WorkbenchHelp.setHelp(getControl(), new DialogPageContextComputer(this, ICHelpContextIds.C_PREF_PAGE)); + } + + /** + * @see FieldEditorPreferencePage#createControl(Composite) + */ + protected void createFieldEditors() { + Composite parent= getFieldEditorParent(); +/* + Label buildText= new Label(parent, SWT.NONE); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan= 3; + buildText.setLayoutData(gd); + buildText.setText(CPlugin.getResourceString(PAGE_DESC)); + FileFieldEditor editor= new FileFieldEditor(PREF_BUILD_LOCATION, CPlugin.getResourceString(BUILD_LOC_LABEL), true, parent) { + protected boolean checkState() { + return true; + } + }; + addField(editor); +*/ + BooleanFieldEditor clearConsole= new BooleanFieldEditor(PREF_CLEAR_CONSOLE, CPlugin.getResourceString(CLEAR_CONSOLE_LABEL), parent); + addField(clearConsole); + + BooleanFieldEditor autoOpenConsole = new BooleanFieldEditor(PREF_AUTO_OPEN_CONSOLE, CPlugin.getResourceString(AUTO_OPEN_CONSOLE_LABEL), parent); + addField(autoOpenConsole); + BooleanFieldEditor consoleOnTop= new BooleanFieldEditor(PREF_CONSOLE_ON_TOP, CPlugin.getResourceString(CONSOLE_ON_TOP_LABEL), parent); + addField(consoleOnTop); + + BooleanFieldEditor linkEditor= new BooleanFieldEditor(PREF_LINK_TO_EDITOR, CPlugin.getResourceString(LINK_TO_EDITOR_LABEL), parent); + addField(linkEditor); + + BooleanFieldEditor showCUChildrenEditor= new BooleanFieldEditor(SHOW_CU_CHILDREN, CPlugin.getResourceString(SHOW_CU_CHILDREN_LABEL), parent); + addField(showCUChildrenEditor); + + addField(new FontFieldEditor(PREF_CONSOLE_FONT, CPlugin.getResourceString(CONSOLE_FONT_LABEL), parent)); + + //addField(new FontFieldEditor(AbstractTextEditor.PREFERENCE_FONT, CPlugin.getResourceString(EDITOR_FONT_LABEL), parent)); + + } + + /** + * Returns the current preference setting if the build console should + * be cleared before each build. + */ + public static boolean isClearBuildConsole() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(PREF_CLEAR_CONSOLE); + } + public static boolean isAutoOpenConsole() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(PREF_AUTO_OPEN_CONSOLE); + } + + public static boolean isConsoleOnTop() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(PREF_CONSOLE_ON_TOP); + } + + public static boolean isLinkToEditor() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(PREF_LINK_TO_EDITOR); + } + + public static boolean showCompilationUnitChildren() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(SHOW_CU_CHILDREN); + } + + /** + * Returns the current preference setting of the build command location. + */ + public static String getBuildLocation() { + return CPlugin.getDefault().getPreferenceStore().getString(PREF_BUILD_LOCATION); + } + + public static boolean isStopOnError() { + return CPlugin.getDefault().getPreferenceStore().getBoolean(PREF_STOP_ON_ERROR); + } + /** + * @see IWorkbenchPreferencePage#init + */ + public void init(IWorkbench workbench) { + } + + /** + * Initializes the default values of this page in the preference bundle. + */ + public static void initDefaults(IPreferenceStore prefs) { + prefs.setDefault(PREF_BUILD_LOCATION, "make"); + prefs.setDefault(PREF_STOP_ON_ERROR, false); + prefs.setDefault(PREF_CLEAR_CONSOLE, true); + prefs.setDefault(PREF_AUTO_OPEN_CONSOLE, false); + prefs.setDefault(PREF_CONSOLE_ON_TOP, true); + prefs.setDefault(PREF_LINK_TO_EDITOR, true); + prefs.setDefault(SHOW_CU_CHILDREN, true); + Font font= JFaceResources.getTextFont(); + if (font != null) { + FontData[] data= font.getFontData(); + if (data != null && data.length > 0) { + //PreferenceConverter.setDefault(prefs, AbstractTextEditor.PREFERENCE_FONT, data[0]); + PreferenceConverter.setDefault(prefs, PREF_CONSOLE_FONT, data[0]); + } + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CProjectPropertyPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CProjectPropertyPage.java new file mode 100644 index 00000000000..fb7ba5d34d8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CProjectPropertyPage.java @@ -0,0 +1,140 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.ui.dialogs.PropertyPage; +import org.eclipse.ui.help.DialogPageContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; +import org.eclipse.cdt.internal.ui.dialogs.StatusTool; +import org.eclipse.cdt.ui.wizards.ReferenceBlock; +import org.eclipse.cdt.ui.wizards.SettingsBlock; +import org.eclipse.cdt.utils.ui.swt.IValidation; +import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; + +public class CProjectPropertyPage extends PropertyPage implements IStatusChangeListener, IValidation { + + private static final String MSG_NOCPROJECT= "CProjectPropertyPage.nocproject"; + private static final String MSG_CLOSEDPROJECT= "CProjectPropertyPage.closedproject"; + + private TabFolder folder; + ReferenceBlock referenceBlock; + SettingsBlock settingsBlock; + + protected Control createContents(Composite parent) { + Composite composite= new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout()); + + IProject project= getProject(); + if (!project.isOpen()) { + contentForClosedProject(composite); + } else { + contentForCProject(composite); + } + + return composite; + } + + private void contentForCProject(Composite parent) { + folder = new TabFolder(parent, SWT.NONE); + folder.setLayout(new TabFolderLayout()); + GridData gdFolder= new GridData(GridData.FILL_HORIZONTAL); + folder.setLayoutData(gdFolder); + + referenceBlock = new ReferenceBlock(this, getProject()); + TabItem item = new TabItem(folder, SWT.NONE); + item.setText(referenceBlock.getLabel()); + Image img = referenceBlock.getImage(); + if (img != null) + item.setImage(img); + item.setData(referenceBlock); + item.setControl(referenceBlock.getControl(folder)); + + settingsBlock = new SettingsBlock(this, getProject()); + TabItem item2 = new TabItem(folder, SWT.NONE); + item2.setText(settingsBlock.getLabel()); + Image img2 = settingsBlock.getImage(); + if (img2 != null) + item2.setImage(img2); + item2.setData(settingsBlock); + item2.setControl(settingsBlock.getControl(folder)); + + WorkbenchHelp.setHelp(parent, new DialogPageContextComputer(this, ICHelpContextIds.PROJECT_PROPERTY_PAGE)); + } + + private void contentForClosedProject(Composite parent) { + Label label= new Label(parent, SWT.LEFT); + label.setText(CPlugin.getResourceString(MSG_CLOSEDPROJECT)); + label.setFont(parent.getFont()); + + noDefaultAndApplyButton(); + } + + public void setComplete(boolean complete) { + boolean ok = true; + if (referenceBlock != null) { + ok = referenceBlock.isValid(); + } + if (ok && settingsBlock != null) { + ok = settingsBlock.isValid(); + } + setValid(ok); + } + + /** + * @see PreferencePage#performOk + */ + public boolean performOk() { + if (settingsBlock != null) + settingsBlock.doRun(getProject(), null); + if (referenceBlock != null) + referenceBlock.doRun(getProject(), null); + return true; + } + + private IProject getProject() { + Object element= getElement(); + if (element instanceof IProject) { + return (IProject)element; + } + return null; + } + + /** + * @see DialogPage#setVisible(boolean) + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible && folder != null) { + settingsBlock.setVisible(visible); + referenceBlock.setVisible(visible); + folder.setFocus(); + } + } + + /** + * @see IStatusChangeListener#statusChanged(IStatus) + */ + public void statusChanged(IStatus status) { + setValid(!status.matches(IStatus.ERROR)); + StatusTool.applyToStatusLine(this, status); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorEditor.java new file mode 100644 index 00000000000..45f695a496e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorEditor.java @@ -0,0 +1,118 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.ColorDialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jface.resource.JFaceResources; + +/** + * A "button" of a certain color determined by the color picker. + */ +public class ColorEditor { + + private Point fExtent; + private Image fImage; + private RGB fColorValue; + private Color fColor; + private Button fButton; + + public ColorEditor(Composite parent) { + + fButton= new Button(parent, SWT.PUSH); + fExtent= computeImageSize(parent); + fImage= new Image(parent.getDisplay(), fExtent.x, fExtent.y); + + GC gc= new GC(fImage); + gc.setBackground(fButton.getBackground()); + gc.fillRectangle(0, 0, fExtent.x, fExtent.y); + gc.dispose(); + + fButton.setImage(fImage); + fButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + ColorDialog colorDialog= new ColorDialog(fButton.getShell()); + colorDialog.setRGB(fColorValue); + RGB newColor = colorDialog.open(); + if (newColor != null) { + fColorValue= newColor; + updateColorImage(); + } + } + }); + + fButton.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { + if (fImage != null) { + fImage.dispose(); + fImage= null; + } + if (fColor != null) { + fColor.dispose(); + fColor= null; + } + } + }); + } + + public RGB getColorValue() { + return fColorValue; + } + + public void setColorValue(RGB rgb) { + fColorValue= rgb; + updateColorImage(); + } + + public Button getButton() { + return fButton; + } + + protected void updateColorImage() { + + Display display= fButton.getDisplay(); + + GC gc= new GC(fImage); + gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); + gc.drawRectangle(0, 2, fExtent.x - 1, fExtent.y - 4); + + if (fColor != null) + fColor.dispose(); + + fColor= new Color(display, fColorValue); + gc.setBackground(fColor); + gc.fillRectangle(1, 3, fExtent.x - 2, fExtent.y - 5); + gc.dispose(); + + fButton.setImage(fImage); + } + + protected Point computeImageSize(Control window) { + GC gc= new GC(window); + Font f= JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT); + gc.setFont(f); + int height= gc.getFontMetrics().getHeight(); + gc.dispose(); + Point p= new Point(height * 3 - 6, height); + return p; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt new file mode 100644 index 00000000000..1a7e359c3dc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt @@ -0,0 +1,10 @@ +/* + * This is sample C code + */ +#include +unsigned static myfunc(int a, char b,) { + /* This comment may span multiple lines. */ + int integer= 0; + // This comment may span only this line + if(integer == 0) printf("zero"); +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java new file mode 100644 index 00000000000..743aa3d357e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/EditTemplateDialog.java @@ -0,0 +1,534 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.ContextTypeRegistry; +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.corext.template.TemplateMessages; +import org.eclipse.cdt.internal.corext.template.TemplateTranslator; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.IContextMenuConstants; +import org.eclipse.cdt.internal.ui.dialogs.StatusDialog; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.ContentAssistPreference; +import org.eclipse.cdt.internal.ui.text.eclipse2.ITextViewerExtension; +import org.eclipse.cdt.internal.ui.text.template.TemplateVariableProcessor; +import org.eclipse.cdt.internal.ui.util.SWTUtil; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.GroupMarker; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; + +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.IUpdate; + + +/** + * Dialog to edit a template. + */ +public class EditTemplateDialog extends StatusDialog { + + private static class SimpleCSourceViewerConfiguration extends CSourceViewerConfiguration { + + private final IContentAssistProcessor fProcessor; + + SimpleCSourceViewerConfiguration(CTextTools tools, CEditor editor, IContentAssistProcessor processor) { + super(tools, editor); + fProcessor= processor; + } + + /* + * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer) + */ + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + + IPreferenceStore store= CPlugin.getDefault().getPreferenceStore(); + + ContentAssistant assistant= new ContentAssistant(); + assistant.setContentAssistProcessor(fProcessor, IDocument.DEFAULT_CONTENT_TYPE); + + //assistant.enableAutoInsert(store.getBoolean(ContentAssistPreference.AUTOINSERT)); + assistant.enableAutoActivation(store.getBoolean(ContentAssistPreference.AUTOACTIVATION)); + assistant.setAutoActivationDelay(store.getInt(ContentAssistPreference.AUTOACTIVATION_DELAY)); + assistant.setProposalPopupOrientation(assistant.PROPOSAL_OVERLAY); + assistant.setContextInformationPopupOrientation(assistant.CONTEXT_INFO_ABOVE); + //assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer)); + + Display display= sourceViewer.getTextWidget().getDisplay(); + + Color background= createColor(store, ContentAssistPreference.PROPOSALS_BACKGROUND, display); + assistant.setContextInformationPopupBackground(background); + //assistant.setContextSelectorBackground(background); + //assistant.setProposalSelectorBackground(background); + + //Color foreground= createColor(store, ContentAssistPreference.PROPOSALS_FOREGROUND, display); + //assistant.setContextInformationPopupForeground(foreground); + //assistant.setContextSelectorForeground(foreground); + //assistant.setProposalSelectorForeground(foreground); + + return assistant; + } + + /** + * Creates a color from the information stored in the given preference store. + * Returns null if there is no such information available. + */ + private Color createColor(IPreferenceStore store, String key, Display display) { + + RGB rgb= null; + + if (store.contains(key)) { + + if (store.isDefault(key)) + rgb= PreferenceConverter.getDefaultColor(store, key); + else + rgb= PreferenceConverter.getColor(store, key); + + if (rgb != null) + return new Color(display, rgb); + } + + return null; + } + } + + private static class TextViewerAction extends Action implements IUpdate { + + private int fOperationCode= -1; + private ITextOperationTarget fOperationTarget; + + public TextViewerAction(ITextViewer viewer, int operationCode) { + fOperationCode= operationCode; + fOperationTarget= viewer.getTextOperationTarget(); + update(); + } + + /** + * Updates the enabled state of the action. + * Fires a property change if the enabled state changes. + * + * @see Action#firePropertyChange(String, Object, Object) + */ + public void update() { + + boolean wasEnabled= isEnabled(); + boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(fOperationCode)); + setEnabled(isEnabled); + + if (wasEnabled != isEnabled) { + firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); + } + } + + /** + * @see Action#run() + */ + public void run() { + if (fOperationCode != -1 && fOperationTarget != null) { + fOperationTarget.doOperation(fOperationCode); + } + } + } + + private final Template fTemplate; + + private Text fNameText; + private Text fDescriptionText; + private Combo fContextCombo; + private SourceViewer fPatternEditor; + private Button fInsertVariableButton; + + private TemplateTranslator fTranslator= new TemplateTranslator(); + private boolean fSuppressError= true; // #4354 + private Map fGlobalActions= new HashMap(10); + private List fSelectionActions = new ArrayList(3); + private Vector fContextTypes= new Vector(); + + private final TemplateVariableProcessor fProcessor= new TemplateVariableProcessor(); + + public EditTemplateDialog(Shell parent, Template template, boolean edit) { + super(parent); + + setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE); + + String title= edit + ? TemplateMessages.getString("EditTemplateDialog.title.edit") //$NON-NLS-1$ + : TemplateMessages.getString("EditTemplateDialog.title.new"); //$NON-NLS-1$ + setTitle(title); + + fTemplate= template; + + ContextTypeRegistry registry= ContextTypeRegistry.getInstance(); + for (Iterator iterator= registry.iterator(); iterator.hasNext(); ) + fContextTypes.add(iterator.next()); + + if (fContextTypes.size() > 0) + fProcessor.setContextType(ContextTypeRegistry.getInstance().getContextType((String) fContextTypes.get(0))); + } + + /* + * @see Dialog#createDialogArea(Composite) + */ + protected Control createDialogArea(Composite ancestor) { + Composite parent= new Composite(ancestor, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + parent.setLayout(layout); + parent.setLayoutData(new GridData(GridData.FILL_BOTH)); + + createLabel(parent, TemplateMessages.getString("EditTemplateDialog.name")); //$NON-NLS-1$ + + Composite composite= new Composite(parent, SWT.NONE); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + layout= new GridLayout(); + layout.numColumns= 3; + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + + fNameText= createText(composite); + fNameText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + if (fSuppressError && (fNameText.getText().trim().length() != 0)) + fSuppressError= false; + + updateButtons(); + } + }); + + createLabel(composite, TemplateMessages.getString("EditTemplateDialog.context")); //$NON-NLS-1$ + fContextCombo= new Combo(composite, SWT.READ_ONLY); + + for (Iterator iterator= fContextTypes.iterator(); iterator.hasNext(); ) + fContextCombo.add((String) iterator.next()); + + fContextCombo.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + String name= fContextCombo.getText(); + fProcessor.setContextType(ContextTypeRegistry.getInstance().getContextType(name)); + } + }); + + createLabel(parent, TemplateMessages.getString("EditTemplateDialog.description")); //$NON-NLS-1$ + fDescriptionText= createText(parent); + + composite= new Composite(parent, SWT.NONE); + composite.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + layout= new GridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 0; + composite.setLayout(layout); + + createLabel(composite, TemplateMessages.getString("EditTemplateDialog.pattern")); //$NON-NLS-1$ + fPatternEditor= createEditor(parent); + + Label filler= new Label(composite, SWT.NONE); + filler.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + + fInsertVariableButton= new Button(composite, SWT.NONE); + fInsertVariableButton.setLayoutData(getButtonGridData(fInsertVariableButton)); + fInsertVariableButton.setText(TemplateMessages.getString("EditTemplateDialog.insert.variable")); //$NON-NLS-1$ + fInsertVariableButton.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + fPatternEditor.getTextWidget().setFocus(); + fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); + } + + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + fNameText.setText(fTemplate.getName()); + fDescriptionText.setText(fTemplate.getDescription()); + fContextCombo.select(getIndex(fTemplate.getContextTypeName())); + + initializeActions(); + + return composite; + } + + private static GridData getButtonGridData(Button button) { + GridData data= new GridData(GridData.FILL_HORIZONTAL); + data.heightHint= SWTUtil.getButtonHeigthHint(button); + + return data; + } + + private static Label createLabel(Composite parent, String name) { + Label label= new Label(parent, SWT.NULL); + label.setText(name); + label.setLayoutData(new GridData()); + + return label; + } + + private static Text createText(Composite parent) { + Text text= new Text(parent, SWT.BORDER); + text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + return text; + } + + private SourceViewer createEditor(Composite parent) { + SourceViewer viewer= new SourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + CTextTools tools= CPlugin.getDefault().getTextTools(); + viewer.configure(new SimpleCSourceViewerConfiguration(tools, null, fProcessor)); + viewer.setEditable(true); + viewer.setDocument(new Document(fTemplate.getPattern())); + + Font font= JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT); + viewer.getTextWidget().setFont(font); + + Control control= viewer.getControl(); + GridData data= new GridData(GridData.FILL_BOTH); + data.widthHint= convertWidthInCharsToPixels(60); + data.heightHint= convertHeightInCharsToPixels(5); + control.setLayoutData(data); + + viewer.addTextListener(new ITextListener() { + public void textChanged(TextEvent event) { + try { + fTranslator.translate(event.getDocumentEvent().getDocument().get()); + } catch (CoreException e) { + CPlugin.log(e); + // XXX dialog + } + + updateUndoAction(); + updateButtons(); + } + }); + + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateSelectionDependentActions(); + } + }); + + if (viewer instanceof ITextViewerExtension) { + ((ITextViewerExtension) viewer).prependVerifyKeyListener(new VerifyKeyListener() { + public void verifyKey(VerifyEvent event) { + handleVerifyKeyPressed(event); + } + }); + } else { + viewer.getTextWidget().addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + handleKeyPressed(e); + } + + public void keyReleased(KeyEvent e) {} + }); + } + + return viewer; + } + + private void handleKeyPressed(KeyEvent event) { + if (event.stateMask != SWT.CTRL) + return; + + switch (event.character) { + case ' ': + fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); + break; + + // CTRL-Z + case (int) 'z' - (int) 'a' + 1: + fPatternEditor.doOperation(ITextOperationTarget.UNDO); + break; + } + } + + private void handleVerifyKeyPressed(VerifyEvent event) { + if (!event.doit) + return; + + if (event.stateMask != SWT.CTRL) + return; + + switch (event.character) { + case ' ': + fPatternEditor.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); + event.doit= false; + break; + + // CTRL-Z + case (int) 'z' - (int) 'a' + 1: + fPatternEditor.doOperation(ITextOperationTarget.UNDO); + event.doit= false; + break; + } + } + + private void initializeActions() { + TextViewerAction action= new TextViewerAction(fPatternEditor, fPatternEditor.UNDO); + action.setText(TemplateMessages.getString("EditTemplateDialog.undo")); //$NON-NLS-1$ + fGlobalActions.put(ITextEditorActionConstants.UNDO, action); + + action= new TextViewerAction(fPatternEditor, fPatternEditor.CUT); + action.setText(TemplateMessages.getString("EditTemplateDialog.cut")); //$NON-NLS-1$ + fGlobalActions.put(ITextEditorActionConstants.CUT, action); + + action= new TextViewerAction(fPatternEditor, fPatternEditor.COPY); + action.setText(TemplateMessages.getString("EditTemplateDialog.copy")); //$NON-NLS-1$ + fGlobalActions.put(ITextEditorActionConstants.COPY, action); + + action= new TextViewerAction(fPatternEditor, fPatternEditor.PASTE); + action.setText(TemplateMessages.getString("EditTemplateDialog.paste")); //$NON-NLS-1$ + fGlobalActions.put(ITextEditorActionConstants.PASTE, action); + + action= new TextViewerAction(fPatternEditor, fPatternEditor.SELECT_ALL); + action.setText(TemplateMessages.getString("EditTemplateDialog.select.all")); //$NON-NLS-1$ + fGlobalActions.put(ITextEditorActionConstants.SELECT_ALL, action); + + action= new TextViewerAction(fPatternEditor, fPatternEditor.CONTENTASSIST_PROPOSALS); + action.setText(TemplateMessages.getString("EditTemplateDialog.content.assist")); //$NON-NLS-1$ + fGlobalActions.put("ContentAssistProposal", action); //$NON-NLS-1$ + + fSelectionActions.add(ITextEditorActionConstants.CUT); + fSelectionActions.add(ITextEditorActionConstants.COPY); + fSelectionActions.add(ITextEditorActionConstants.PASTE); + + // create context menu + MenuManager manager= new MenuManager(null, null); + manager.setRemoveAllWhenShown(true); + manager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager mgr) { + fillContextMenu(mgr); + } + }); + + StyledText text= fPatternEditor.getTextWidget(); + Menu menu= manager.createContextMenu(text); + text.setMenu(menu); + } + + private void fillContextMenu(IMenuManager menu) { + menu.add(new GroupMarker(ITextEditorActionConstants.GROUP_UNDO)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO)); + + menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.CUT)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.COPY)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.PASTE)); + menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, (IAction) fGlobalActions.get(ITextEditorActionConstants.SELECT_ALL)); + + menu.add(new Separator(IContextMenuConstants.GROUP_GENERATE)); + menu.appendToGroup(IContextMenuConstants.GROUP_GENERATE, (IAction) fGlobalActions.get("ContentAssistProposal")); //$NON-NLS-1$ + } + + protected void updateSelectionDependentActions() { + Iterator iterator= fSelectionActions.iterator(); + while (iterator.hasNext()) + updateAction((String)iterator.next()); + } + + protected void updateUndoAction() { + IAction action= (IAction) fGlobalActions.get(ITextEditorActionConstants.UNDO); + if (action instanceof IUpdate) + ((IUpdate) action).update(); + } + + protected void updateAction(String actionId) { + IAction action= (IAction) fGlobalActions.get(actionId); + if (action instanceof IUpdate) + ((IUpdate) action).update(); + } + + private int getIndex(String context) { + ContextTypeRegistry registry= ContextTypeRegistry.getInstance(); + registry.getContextType(context); + + if (context == null) + return -1; + + return fContextTypes.indexOf(context); + } + + protected void okPressed() { + fTemplate.setName(fNameText.getText()); + fTemplate.setDescription(fDescriptionText.getText()); + fTemplate.setContext(fContextCombo.getText()); + fTemplate.setPattern(fPatternEditor.getTextWidget().getText()); + + super.okPressed(); + } + + private void updateButtons() { + boolean valid= fNameText.getText().trim().length() != 0; + + StatusInfo status= new StatusInfo(); + + if (!valid) { + if (fSuppressError) + status.setError(""); //$NON-NLS-1$ + else + status.setError(TemplateMessages.getString("EditTemplateDialog.error.noname")); //$NON-NLS-1$ + } else if (fTranslator.getErrorMessage() != null) { + status.setError(fTranslator.getErrorMessage()); + } + + updateStatus(status); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OverlayPreferenceStore.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OverlayPreferenceStore.java new file mode 100644 index 00000000000..62c24384ee9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/OverlayPreferenceStore.java @@ -0,0 +1,447 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +/** + * An overlaying preference store. + */ +public class OverlayPreferenceStore implements IPreferenceStore { + + + public static final class TypeDescriptor { + private TypeDescriptor() { + } + }; + + public static final TypeDescriptor BOOLEAN= new TypeDescriptor(); + public static final TypeDescriptor DOUBLE= new TypeDescriptor(); + public static final TypeDescriptor FLOAT= new TypeDescriptor(); + public static final TypeDescriptor INT= new TypeDescriptor(); + public static final TypeDescriptor LONG= new TypeDescriptor(); + public static final TypeDescriptor STRING= new TypeDescriptor(); + + public static class OverlayKey { + + TypeDescriptor fDescriptor; + String fKey; + + public OverlayKey(TypeDescriptor descriptor, String key) { + fDescriptor= descriptor; + fKey= key; + } + }; + + private class PropertyListener implements IPropertyChangeListener { + + /* + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + OverlayKey key= findOverlayKey(event.getProperty()); + if (key != null) + propagateProperty(fParent, key, fStore); + } + }; + + + private IPreferenceStore fParent; + private IPreferenceStore fStore; + private OverlayKey[] fOverlayKeys; + + private PropertyListener fPropertyListener; + + + public OverlayPreferenceStore(IPreferenceStore parent, OverlayKey[] overlayKeys) { + fParent= parent; + fOverlayKeys= overlayKeys; + fStore= new PreferenceStore(); + } + + private OverlayKey findOverlayKey(String key) { + for (int i= 0; i < fOverlayKeys.length; i++) { + if (fOverlayKeys[i].fKey.equals(key)) + return fOverlayKeys[i]; + } + return null; + } + + private boolean covers(String key) { + return (findOverlayKey(key) != null); + } + + private void propagateProperty(IPreferenceStore orgin, OverlayKey key, IPreferenceStore target) { + + if (orgin.isDefault(key.fKey)) { + if (!target.isDefault(key.fKey)) + target.setToDefault(key.fKey); + return; + } + + TypeDescriptor d= key.fDescriptor; + if (BOOLEAN == d) { + + boolean originValue= orgin.getBoolean(key.fKey); + boolean targetValue= target.getBoolean(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (DOUBLE == d) { + + double originValue= orgin.getDouble(key.fKey); + double targetValue= target.getDouble(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (FLOAT == d) { + + float originValue= orgin.getFloat(key.fKey); + float targetValue= target.getFloat(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (INT == d) { + + int originValue= orgin.getInt(key.fKey); + int targetValue= target.getInt(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (LONG == d) { + + long originValue= orgin.getLong(key.fKey); + long targetValue= target.getLong(key.fKey); + if (targetValue != originValue) + target.setValue(key.fKey, originValue); + + } else if (STRING == d) { + + String originValue= orgin.getString(key.fKey); + String targetValue= target.getString(key.fKey); + if (targetValue != null && originValue != null && !targetValue.equals(originValue)) + target.setValue(key.fKey, originValue); + + } + } + + public void propagate() { + for (int i= 0; i < fOverlayKeys.length; i++) + propagateProperty(fStore, fOverlayKeys[i], fParent); + } + + private void loadProperty(IPreferenceStore orgin, OverlayKey key, IPreferenceStore target, boolean forceInitialization) { + TypeDescriptor d= key.fDescriptor; + if (BOOLEAN == d) { + + if (forceInitialization) + target.setValue(key.fKey, true); + target.setValue(key.fKey, orgin.getBoolean(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultBoolean(key.fKey)); + + } else if (DOUBLE == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1.0D); + target.setValue(key.fKey, orgin.getDouble(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultDouble(key.fKey)); + + } else if (FLOAT == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1.0F); + target.setValue(key.fKey, orgin.getFloat(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultFloat(key.fKey)); + + } else if (INT == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1); + target.setValue(key.fKey, orgin.getInt(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultInt(key.fKey)); + + } else if (LONG == d) { + + if (forceInitialization) + target.setValue(key.fKey, 1L); + target.setValue(key.fKey, orgin.getLong(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultLong(key.fKey)); + + } else if (STRING == d) { + + if (forceInitialization) + target.setValue(key.fKey, "1"); + target.setValue(key.fKey, orgin.getString(key.fKey)); + target.setDefault(key.fKey, orgin.getDefaultString(key.fKey)); + + } + } + + public void load() { + for (int i= 0; i < fOverlayKeys.length; i++) + loadProperty(fParent, fOverlayKeys[i], fStore, true); + } + + public void loadDefaults() { + for (int i= 0; i < fOverlayKeys.length; i++) + setToDefault(fOverlayKeys[i].fKey); + } + + public void start() { + if (fPropertyListener == null) { + fPropertyListener= new PropertyListener(); + fParent.addPropertyChangeListener(fPropertyListener); + } + } + + public void stop() { + if (fPropertyListener != null) { + fParent.removePropertyChangeListener(fPropertyListener); + fPropertyListener= null; + } + } + + /* + * @see IPreferenceStore#addPropertyChangeListener(IPropertyChangeListener) + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + fStore.addPropertyChangeListener(listener); + } + + /* + * @see IPreferenceStore#removePropertyChangeListener(IPropertyChangeListener) + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + fStore.removePropertyChangeListener(listener); + } + + /* + * @see IPreferenceStore#firePropertyChangeEvent(String, Object, Object) + */ + public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { + fStore.firePropertyChangeEvent(name, oldValue, newValue); + } + + /* + * @see IPreferenceStore#contains(String) + */ + public boolean contains(String name) { + return fStore.contains(name); + } + + /* + * @see IPreferenceStore#getBoolean(String) + */ + public boolean getBoolean(String name) { + return fStore.getBoolean(name); + } + + /* + * @see IPreferenceStore#getDefaultBoolean(String) + */ + public boolean getDefaultBoolean(String name) { + return fStore.getDefaultBoolean(name); + } + + /* + * @see IPreferenceStore#getDefaultDouble(String) + */ + public double getDefaultDouble(String name) { + return fStore.getDefaultDouble(name); + } + + /* + * @see IPreferenceStore#getDefaultFloat(String) + */ + public float getDefaultFloat(String name) { + return fStore.getDefaultFloat(name); + } + + /* + * @see IPreferenceStore#getDefaultInt(String) + */ + public int getDefaultInt(String name) { + return fStore.getDefaultInt(name); + } + + /* + * @see IPreferenceStore#getDefaultLong(String) + */ + public long getDefaultLong(String name) { + return fStore.getDefaultLong(name); + } + + /* + * @see IPreferenceStore#getDefaultString(String) + */ + public String getDefaultString(String name) { + return fStore.getDefaultString(name); + } + + /* + * @see IPreferenceStore#getDouble(String) + */ + public double getDouble(String name) { + return fStore.getDouble(name); + } + + /* + * @see IPreferenceStore#getFloat(String) + */ + public float getFloat(String name) { + return fStore.getFloat(name); + } + + /* + * @see IPreferenceStore#getInt(String) + */ + public int getInt(String name) { + return fStore.getInt(name); + } + + /* + * @see IPreferenceStore#getLong(String) + */ + public long getLong(String name) { + return fStore.getLong(name); + } + + /* + * @see IPreferenceStore#getString(String) + */ + public String getString(String name) { + return fStore.getString(name); + } + + /* + * @see IPreferenceStore#isDefault(String) + */ + public boolean isDefault(String name) { + return fStore.isDefault(name); + } + + /* + * @see IPreferenceStore#needsSaving() + */ + public boolean needsSaving() { + return fStore.needsSaving(); + } + + /* + * @see IPreferenceStore#putValue(String, String) + */ + public void putValue(String name, String value) { + if (covers(name)) + fStore.putValue(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, double) + */ + public void setDefault(String name, double value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, float) + */ + public void setDefault(String name, float value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, int) + */ + public void setDefault(String name, int value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, long) + */ + public void setDefault(String name, long value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, String) + */ + public void setDefault(String name, String value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setDefault(String, boolean) + */ + public void setDefault(String name, boolean value) { + if (covers(name)) + fStore.setDefault(name, value); + } + + /* + * @see IPreferenceStore#setToDefault(String) + */ + public void setToDefault(String name) { + fStore.setToDefault(name); + } + + /* + * @see IPreferenceStore#setValue(String, double) + */ + public void setValue(String name, double value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, float) + */ + public void setValue(String name, float value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, int) + */ + public void setValue(String name, int value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, long) + */ + public void setValue(String name, long value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, String) + */ + public void setValue(String name, String value) { + if (covers(name)) + fStore.setValue(name, value); + } + + /* + * @see IPreferenceStore#setValue(String, boolean) + */ + public void setValue(String name, boolean value) { + if (covers(name)) + fStore.setValue(name, value); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TemplatePreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TemplatePreferencePage.java new file mode 100644 index 00000000000..cb18a8c9da1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/TemplatePreferencePage.java @@ -0,0 +1,593 @@ +package org.eclipse.cdt.internal.ui.preferences; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.ContextTypeRegistry; +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.corext.template.TemplateMessages; +import org.eclipse.cdt.internal.corext.template.TemplateSet; +import org.eclipse.cdt.internal.corext.template.Templates; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.internal.ui.text.CTextTools; +import org.eclipse.cdt.internal.ui.text.template.TemplateContentProvider; +import org.eclipse.cdt.internal.ui.text.template.TemplateLabelProvider; +import org.eclipse.cdt.internal.ui.util.SWTUtil; +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; + +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.help.DialogPageContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; + + +public class TemplatePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + // preference store keys + private static final String PREF_FORMAT_TEMPLATES= CPlugin.PLUGIN_ID + ".template.format"; //$NON-NLS-1$ + + private Templates fTemplates; + + private CheckboxTableViewer fTableViewer; + private Button fAddButton; + private Button fEditButton; + private Button fImportButton; + private Button fExportButton; + private Button fExportAllButton; + private Button fRemoveButton; + private Button fEnableAllButton; + private Button fDisableAllButton; + + private SourceViewer fPatternViewer; + //private Button fFormatButton; + + public TemplatePreferencePage() { + super(); + + setPreferenceStore(CPlugin.getDefault().getPreferenceStore()); + setDescription(TemplateMessages.getString("TemplatePreferencePage.message")); //$NON-NLS-1$ + + fTemplates= Templates.getInstance(); + } + + /** + * @see PreferencePage#createContents(Composite) + */ + protected Control createContents(Composite ancestor) { + Composite parent= new Composite(ancestor, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + layout.marginHeight= 0; + layout.marginWidth= 0; + parent.setLayout(layout); + + Table table= new Table(parent, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); + + GridData data= new GridData(GridData.FILL_BOTH); + data.widthHint= convertWidthInCharsToPixels(80); + data.heightHint= convertHeightInCharsToPixels(10); + table.setLayoutData(data); + + table.setHeaderVisible(true); + table.setLinesVisible(true); + + TableLayout tableLayout= new TableLayout(); + table.setLayout(tableLayout); + + TableColumn column1= new TableColumn(table, SWT.NONE); + column1.setText(TemplateMessages.getString("TemplatePreferencePage.column.name")); //$NON-NLS-1$ + + TableColumn column2= new TableColumn(table, SWT.NONE); + column2.setText(TemplateMessages.getString("TemplatePreferencePage.column.context")); //$NON-NLS-1$ + + TableColumn column3= new TableColumn(table, SWT.NONE); + column3.setText(TemplateMessages.getString("TemplatePreferencePage.column.description")); //$NON-NLS-1$ + + tableLayout.addColumnData(new ColumnWeightData(30)); + tableLayout.addColumnData(new ColumnWeightData(20)); + tableLayout.addColumnData(new ColumnWeightData(70)); + + fTableViewer= new CheckboxTableViewer(table); + fTableViewer.setLabelProvider(new TemplateLabelProvider()); + fTableViewer.setContentProvider(new TemplateContentProvider()); + + fTableViewer.setSorter(new ViewerSorter() { + public int compare(Viewer viewer, Object object1, Object object2) { + if ((object1 instanceof Template) && (object2 instanceof Template)) { + Template left= (Template) object1; + Template right= (Template) object2; + int result= left.getName().compareToIgnoreCase(right.getName()); + if (result != 0) + return result; + return left.getDescription().compareToIgnoreCase(right.getDescription()); + } + return super.compare(viewer, object1, object2); + } + + public boolean isSorterProperty(Object element, String property) { + return true; + } + }); + + fTableViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent e) { + edit(); + } + }); + + fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent e) { + selectionChanged1(); + } + }); + + fTableViewer.addCheckStateListener(new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + Template template= (Template) event.getElement(); + template.setEnabled(event.getChecked()); + } + }); + + Composite buttons= new Composite(parent, SWT.NULL); + buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + layout= new GridLayout(); + layout.marginHeight= 0; + layout.marginWidth= 0; + buttons.setLayout(layout); + + fAddButton= new Button(buttons, SWT.PUSH); + fAddButton.setLayoutData(getButtonGridData(fAddButton)); + fAddButton.setText(TemplateMessages.getString("TemplatePreferencePage.new")); //$NON-NLS-1$ + fAddButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + add(); + } + }); + + fEditButton= new Button(buttons, SWT.PUSH); + fEditButton.setLayoutData(getButtonGridData(fEditButton)); + fEditButton.setText(TemplateMessages.getString("TemplatePreferencePage.edit")); //$NON-NLS-1$ + fEditButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + edit(); + } + }); + + fRemoveButton= new Button(buttons, SWT.PUSH); + fRemoveButton.setLayoutData(getButtonGridData(fRemoveButton)); + fRemoveButton.setText(TemplateMessages.getString("TemplatePreferencePage.remove")); //$NON-NLS-1$ + fRemoveButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + remove(); + } + }); + + createSpacer(buttons); + + fImportButton= new Button(buttons, SWT.PUSH); + fImportButton.setLayoutData(getButtonGridData(fImportButton)); + fImportButton.setText(TemplateMessages.getString("TemplatePreferencePage.import")); //$NON-NLS-1$ + fImportButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + import_(); + } + }); + + fExportButton= new Button(buttons, SWT.PUSH); + fExportButton.setLayoutData(getButtonGridData(fExportButton)); + fExportButton.setText(TemplateMessages.getString("TemplatePreferencePage.export")); //$NON-NLS-1$ + fExportButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + export(); + } + }); + + fExportAllButton= new Button(buttons, SWT.PUSH); + fExportAllButton.setLayoutData(getButtonGridData(fExportAllButton)); + fExportAllButton.setText(TemplateMessages.getString("TemplatePreferencePage.export.all")); //$NON-NLS-1$ + fExportAllButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + exportAll(); + } + }); + + createSpacer(buttons); + + fEnableAllButton= new Button(buttons, SWT.PUSH); + fEnableAllButton.setLayoutData(getButtonGridData(fEnableAllButton)); + fEnableAllButton.setText(TemplateMessages.getString("TemplatePreferencePage.enable.all")); //$NON-NLS-1$ + fEnableAllButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + enableAll(true); + } + }); + + fDisableAllButton= new Button(buttons, SWT.PUSH); + fDisableAllButton.setLayoutData(getButtonGridData(fDisableAllButton)); + fDisableAllButton.setText(TemplateMessages.getString("TemplatePreferencePage.disable.all")); //$NON-NLS-1$ + fDisableAllButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + enableAll(false); + } + }); + + fPatternViewer= createViewer(parent); + + createSpacer(parent); + + //fFormatButton= new Button(parent, SWT.CHECK); + //fFormatButton.setText(TemplateMessages.getString("TemplatePreferencePage.use.code.formatter")); //$NON-NLS-1$ + + fTableViewer.setInput(fTemplates); + fTableViewer.setAllChecked(false); + fTableViewer.setCheckedElements(getEnabledTemplates()); + + //IPreferenceStore prefs= CPlugin.getDefault().getPreferenceStore(); + //fFormatButton.setSelection(prefs.getBoolean(PREF_FORMAT_TEMPLATES)); + + updateButtons(); + + WorkbenchHelp.setHelp(parent, new DialogPageContextComputer(this, ICHelpContextIds.TEMPLATE_PREFERENCE_PAGE)); + + return parent; + } + + private Template[] getEnabledTemplates() { + Template[] templates= fTemplates.getTemplates(); + + List list= new ArrayList(templates.length); + + for (int i= 0; i != templates.length; i++) + if (templates[i].isEnabled()) + list.add(templates[i]); + + return (Template[]) list.toArray(new Template[list.size()]); + } + + private SourceViewer createViewer(Composite parent) { + Label label= new Label(parent, SWT.NONE); + label.setText("Preview:"); + GridData data= new GridData(); + data.horizontalSpan= 2; + label.setLayoutData(data); + + SourceViewer viewer= new SourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + CTextTools tools= CPlugin.getDefault().getTextTools(); + viewer.configure(new CSourceViewerConfiguration(tools, null)); + viewer.setEditable(false); + viewer.setDocument(new Document()); + viewer.getTextWidget().setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + + Font font= JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT); + viewer.getTextWidget().setFont(font); + + Control control= viewer.getControl(); + data= new GridData(GridData.FILL_BOTH); + data.heightHint= convertHeightInCharsToPixels(5); + control.setLayoutData(data); + + return viewer; + } + + public void createSpacer(Composite parent) { + Label spacer= new Label(parent, SWT.NONE); + GridData data= new GridData(); + data.horizontalAlignment= GridData.FILL; + data.verticalAlignment= GridData.BEGINNING; + data.heightHint= 4; + spacer.setLayoutData(data); + } + + private static GridData getButtonGridData(Button button) { + GridData data= new GridData(GridData.FILL_HORIZONTAL); + data.widthHint= SWTUtil.getButtonWidthHint(button); + data.heightHint= SWTUtil.getButtonHeigthHint(button); + + return data; + } + + private void selectionChanged1() { + IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection(); + + if (selection.size() == 1) { + Template template= (Template) selection.getFirstElement(); + fPatternViewer.getTextWidget().setText(template.getPattern()); + } else { + fPatternViewer.getTextWidget().setText(""); //$NON-NLS-1$ + } + + updateButtons(); + } + + private void updateButtons() { + int selectionCount= ((IStructuredSelection) fTableViewer.getSelection()).size(); + int itemCount= fTableViewer.getTable().getItemCount(); + + fEditButton.setEnabled(selectionCount == 1); + fExportButton.setEnabled(selectionCount > 0); + fRemoveButton.setEnabled(selectionCount > 0 && selectionCount <= itemCount); + fEnableAllButton.setEnabled(itemCount > 0); + fDisableAllButton.setEnabled(itemCount > 0); + } + + private void add() { + + Template template= new Template(); + + ContextTypeRegistry registry=ContextTypeRegistry.getInstance(); + ContextType type= registry.getContextType("java"); + + String contextTypeName; + if (type != null) + contextTypeName= type.getName(); + else { + Iterator iterator= registry.iterator(); + contextTypeName= (String) iterator.next(); + } + template.setContext(contextTypeName); //$NON-NLS-1$ + + EditTemplateDialog dialog= new EditTemplateDialog(getShell(), template, false); + if (dialog.open() == dialog.OK) { + fTemplates.add(template); + fTableViewer.refresh(); + fTableViewer.setChecked(template, template.isEnabled()); + fTableViewer.setSelection(new StructuredSelection(template)); + } + } + + private void edit() { + IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection(); + + Object[] objects= selection.toArray(); + if ((objects == null) || (objects.length != 1)) + return; + + Template template= (Template) selection.getFirstElement(); + edit(template); + } + + private void edit(Template template) { + Template newTemplate= new Template(template); + EditTemplateDialog dialog= new EditTemplateDialog(getShell(), newTemplate, true); + if (dialog.open() == dialog.OK) { + + if (!newTemplate.getName().equals(template.getName()) && + MessageDialog.openQuestion(getShell(), + TemplateMessages.getString("TemplatePreferencePage.question.create.new.title"), + TemplateMessages.getString("TemplatePreferencePage.question.create.new.message"))) + { + template= newTemplate; + fTemplates.add(template); + fTableViewer.refresh(); + } else { + template.setName(newTemplate.getName()); + template.setDescription(newTemplate.getDescription()); + template.setContext(newTemplate.getContextTypeName()); + template.setPattern(newTemplate.getPattern()); + fTableViewer.refresh(template); + } + fTableViewer.setChecked(template, template.isEnabled()); + fTableViewer.setSelection(new StructuredSelection(template)); + } + } + + private void import_() { + FileDialog dialog= new FileDialog(getShell()); + dialog.setText(TemplateMessages.getString("TemplatePreferencePage.import.title")); //$NON-NLS-1$ + dialog.setFilterExtensions(new String[] {TemplateMessages.getString("TemplatePreferencePage.import.extension")}); //$NON-NLS-1$ + String path= dialog.open(); + + if (path == null) + return; + + try { + fTemplates.addFromFile(new File(path)); + + fTableViewer.refresh(); + fTableViewer.setAllChecked(false); + fTableViewer.setCheckedElements(getEnabledTemplates()); + + } catch (CoreException e) { + openReadErrorDialog(e); + } + } + + private void exportAll() { + export(fTemplates); + } + + private void export() { + IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection(); + Object[] templates= selection.toArray(); + + TemplateSet templateSet= new TemplateSet(); + for (int i= 0; i != templates.length; i++) + templateSet.add((Template) templates[i]); + + export(templateSet); + } + + private void export(TemplateSet templateSet) { + FileDialog dialog= new FileDialog(getShell(), SWT.SAVE); + dialog.setText(TemplateMessages.getFormattedString("TemplatePreferencePage.export.title", new Integer(templateSet.getTemplates().length))); //$NON-NLS-1$ + dialog.setFilterExtensions(new String[] {TemplateMessages.getString("TemplatePreferencePage.export.extension")}); //$NON-NLS-1$ + dialog.setFileName(TemplateMessages.getString("TemplatePreferencePage.export.filename")); //$NON-NLS-1$ + String path= dialog.open(); + + if (path == null) + return; + + File file= new File(path); + + if (!file.exists() || confirmOverwrite(file)) { + try { + templateSet.saveToFile(file); + } catch (CoreException e) { + CPlugin.log(e); + openWriteErrorDialog(e); + } + } + } + + private boolean confirmOverwrite(File file) { + return MessageDialog.openQuestion(getShell(), + TemplateMessages.getString("TemplatePreferencePage.export.exists.title"), + TemplateMessages.getFormattedString("TemplatePreferencePage.export.exists.message", file.getAbsolutePath())); + } + + private void remove() { + IStructuredSelection selection= (IStructuredSelection) fTableViewer.getSelection(); + + Iterator elements= selection.iterator(); + while (elements.hasNext()) { + Template template= (Template) elements.next(); + fTemplates.remove(template); + } + + fTableViewer.refresh(); + } + + private void enableAll(boolean enable) { + Template[] templates= fTemplates.getTemplates(); + for (int i= 0; i != templates.length; i++) + templates[i].setEnabled(enable); + + fTableViewer.setAllChecked(enable); + } + + /* + * @see IWorkbenchPreferencePage#init(IWorkbench) + */ + public void init(IWorkbench workbench) {} + + /* + * @see Control#setVisible(boolean) + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) + setTitle(TemplateMessages.getString("TemplatePreferencePage.title")); //$NON-NLS-1$ + } + + /* + * @see PreferencePage#performDefaults() + */ + protected void performDefaults() { + //IPreferenceStore prefs= CPlugin.getDefault().getPreferenceStore(); + //fFormatButton.setSelection(prefs.getDefaultBoolean(PREF_FORMAT_TEMPLATES)); + + try { + fTemplates.restoreDefaults(); + } catch (CoreException e) { + CPlugin.log(e); + openReadErrorDialog(e); + } + + // refresh + fTableViewer.refresh(); + fTableViewer.setAllChecked(false); + fTableViewer.setCheckedElements(getEnabledTemplates()); + } + + /* + * @see PreferencePage#performOk() + */ + public boolean performOk() { + //IPreferenceStore prefs= CPlugin.getDefault().getPreferenceStore(); + //prefs.setValue(PREF_FORMAT_TEMPLATES, fFormatButton.getSelection()); + + try { + fTemplates.save(); + } catch (CoreException e) { + CPlugin.log(e); + openWriteErrorDialog(e); + } + + return super.performOk(); + } + + /* + * @see PreferencePage#performCancel() + */ + public boolean performCancel() { + try { + fTemplates.reset(); + } catch (CoreException e) { + CPlugin.log(e); + openReadErrorDialog(e); + } + + return super.performCancel(); + } + + /** + * Initializes the default values of this page in the preference bundle. + * Will be called on startup of the JavaPlugin + */ + public static void initDefaults(IPreferenceStore prefs) { + prefs.setDefault(PREF_FORMAT_TEMPLATES, true); + } + + public static boolean useCodeFormatter() { + IPreferenceStore prefs= CPlugin.getDefault().getPreferenceStore(); + return prefs.getBoolean(PREF_FORMAT_TEMPLATES); + } + + private void openReadErrorDialog(CoreException e) { + ErrorDialog.openError(getShell(), + TemplateMessages.getString("TemplatePreferencePage.error.read.title"), //$NON-NLS-1$ + null, e.getStatus()); + } + + private void openWriteErrorDialog(CoreException e) { + ErrorDialog.openError(getShell(), + TemplateMessages.getString("TemplatePreferencePage.error.write.title"), //$NON-NLS-1$ + null, e.getStatus()); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractCScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractCScanner.java new file mode 100644 index 00000000000..a00acfaaeb9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractCScanner.java @@ -0,0 +1,219 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.resource.StringConverter; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.BufferedRuleBasedScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * Initialized with a color manager and a preference store, its subclasses are + * only responsible for providing a list of preference keys based on which tokens + * are generated and to use this tokens to define the rules controlling this scanner. + */ +public abstract class AbstractCScanner extends BufferedRuleBasedScanner { + + + private IColorManager fColorManager; + private IPreferenceStore fPreferenceStore; + + private Map fTokenMap= new HashMap(); + private String[] fPropertyNamesColor; + private String[] fPropertyNamesStyle; + + private IToken fDefaultToken; + + + /** + * Returns the list of preference keys which define the tokens + * used in the rules of this scanner. + */ + abstract protected String[] getTokenProperties(); + + /** + * Creates the list of rules controlling this scanner. + */ + abstract protected List createRules(); + + + /** + * Creates an abstract Java scanner. + */ + public AbstractCScanner(IColorManager manager, IPreferenceStore store) { + super(); + fColorManager= manager; + fPreferenceStore= store; + } + + /** + * Creates an abstract Java scanner. + */ + public AbstractCScanner(IColorManager manager, IPreferenceStore store, int bufsize) { + super(bufsize); + fColorManager= manager; + fPreferenceStore= store; + } + /** + * Must be called after the constructor has been called. + */ + public final void initialize() { + + fPropertyNamesColor= getTokenProperties(); + int length= fPropertyNamesColor.length; + fPropertyNamesStyle= new String[length]; + for (int i= 0; i < length; i++) { + fPropertyNamesStyle[i]= fPropertyNamesColor[i] + "_bold"; + addToken(fPropertyNamesColor[i], fPropertyNamesStyle[i]); + } + + initializeRules(); + } + + private void addToken(String colorKey, String styleKey) { + RGB rgb= PreferenceConverter.getColor(fPreferenceStore, colorKey); + if (fColorManager instanceof IColorManagerExtension) { + IColorManagerExtension ext= (IColorManagerExtension) fColorManager; + ext.unbindColor(colorKey); + ext.bindColor(colorKey, rgb); + } + + boolean bold= fPreferenceStore.getBoolean(styleKey); + fTokenMap.put(colorKey, new Token(new TextAttribute(fColorManager.getColor(colorKey), null, bold ? SWT.BOLD : SWT.NORMAL))); + } + + protected Token getToken(String key) { + return (Token) fTokenMap.get(key); + } + + private void initializeRules() { + List rules= createRules(); + if (rules != null) { + IRule[] result= new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } + } + + private int indexOf(String property) { + if (property != null) { + int length= fPropertyNamesColor.length; + for (int i= 0; i < length; i++) { + if (property.equals(fPropertyNamesColor[i]) || property.equals(fPropertyNamesStyle[i])) + return i; + } + } + return -1; + } + + public boolean affectsBehavior(PropertyChangeEvent event) { + return indexOf(event.getProperty()) >= 0; + } + + public void adaptToPreferenceChange(PropertyChangeEvent event) { + String p= event.getProperty(); + int index= indexOf(p); + Token token = getToken(fPropertyNamesColor[index]); + if (fPropertyNamesColor[index].equals(p)) + adaptToColorChange(token, event); + else + adaptToStyleChange(token, event); + } + + private void adaptToColorChange(Token token, PropertyChangeEvent event) { + RGB rgb= null; + + Object value= event.getNewValue(); + if (value instanceof RGB) + rgb= (RGB) value; + else if (value instanceof String) { + rgb= StringConverter.asRGB((String) value); + } + + if (rgb != null) { + + String property= event.getProperty(); + + if (fColorManager instanceof IColorManagerExtension) { + IColorManagerExtension ext= (IColorManagerExtension) fColorManager; + ext.unbindColor(property); + ext.bindColor(property, rgb); + } + + Object data= token.getData(); + if (data instanceof TextAttribute) { + TextAttribute oldAttr= (TextAttribute) data; + token.setData(new TextAttribute(fColorManager.getColor(property), oldAttr.getBackground(), oldAttr.getStyle())); + } + } + } + + private void adaptToStyleChange(Token token, PropertyChangeEvent event) { + boolean bold= false; + Object value= event.getNewValue(); + if (value instanceof Boolean) + bold= ((Boolean) value).booleanValue(); + else if (value instanceof String) { + String s= (String) value; + if (IPreferenceStore.TRUE.equals(s)) + bold= true; + else if (IPreferenceStore.FALSE.equals(s)) + bold= false; + } + + Object data= token.getData(); + if (data instanceof TextAttribute) { + TextAttribute oldAttr= (TextAttribute) data; + boolean isBold= (oldAttr.getStyle() == SWT.BOLD); + if (isBold != bold) + token.setData(new TextAttribute(oldAttr.getForeground(), oldAttr.getBackground(), bold ? SWT.BOLD : SWT.NORMAL)); + } + } + + /** + * Returns the next token in the document. + * + * @return the next token in the document + */ + public IToken nextToken() { + + IToken token; + + while (true) { + + fTokenOffset= fOffset; + fColumn= UNDEFINED; + + for (int i= 0; i < fRules.length; i++) { + token= (fRules[i].evaluate(this)); + if (!token.isUndefined()) + return token; + } + if (read() == EOF) + return Token.EOF; + else + return fDefaultToken; + } + } + + public void setDefaultReturnToken(IToken token) { + fDefaultToken = token; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAnnotationHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAnnotationHover.java new file mode 100644 index 00000000000..0abdc2c28f0 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAnnotationHover.java @@ -0,0 +1,161 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; + + +import org.eclipse.core.resources.IMarker; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; + + +import org.eclipse.ui.texteditor.MarkerAnnotation; + + +import org.eclipse.cdt.internal.ui.text.LineBreakingReader; + + +import org.eclipse.cdt.internal.ui.CPlugin; + + +public class CAnnotationHover implements IAnnotationHover { + + /** + * Returns the distance to the ruler line. + */ + protected int compareRulerLine(Position position, IDocument document, int line) { + + if (position.getOffset() > -1 && position.getLength() > -1) { + try { + int markerLine= document.getLineOfOffset(position.getOffset()); + if (line == markerLine) + return 1; + if (markerLine <= line && line <= document.getLineOfOffset(position.getOffset() + position.getLength())) + return 2; + } catch (BadLocationException x) { + } + } + + return 0; + } + + /** + * Selects one marker from the two lists. + */ + protected IMarker select(List firstChoice, List secondChoice) { + if (!firstChoice.isEmpty()) + return (IMarker) firstChoice.get(0); + if (!secondChoice.isEmpty()) + return (IMarker) secondChoice.get(0); + return null; + } + + /** + * Returns one marker which includes the ruler's line of activity. + */ + protected IMarker getMarker(ISourceViewer viewer, int line) { + + IDocument document= viewer.getDocument(); + IAnnotationModel model= viewer.getAnnotationModel(); + + if (model == null) + return null; + + List exact= new ArrayList(); + List including= new ArrayList(); + + Iterator e= model.getAnnotationIterator(); + while (e.hasNext()) { + Object o= e.next(); + if (o instanceof MarkerAnnotation) { + MarkerAnnotation a= (MarkerAnnotation) o; + switch (compareRulerLine(model.getPosition(a), document, line)) { + case 1: + exact.add(a.getMarker()); + break; + case 2: + including.add(a.getMarker()); + break; + } + } + } + + return select(exact, including); + } + + + + /** + * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int) + */ + public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) { + IMarker marker= getMarker(sourceViewer, lineNumber); + if (marker != null) { + String text= marker.getAttribute(IMarker.MESSAGE, (String) null); + if (text != null) { + return formatHoverText(text, sourceViewer.getTextWidget().getDisplay()); + } + } + return null; + } + + /* + * Formats the message of this hover to fit onto the screen. + */ + private String formatHoverText(String text, Display display) { + String lineDelim= System.getProperty("line.separator", "\n"); + + Reader textReader= new StringReader(text); + GC gc= new GC(display); + try { + StringBuffer buf= new StringBuffer(); + + LineBreakingReader reader= new LineBreakingReader(textReader, gc, getHoverWidth(display)); + String line= reader.readLine(); + while (line != null) { + if (buf.length() != 0) { + buf.append(lineDelim); + } + buf.append(line); + line= reader.readLine(); + } + return buf.toString(); + } catch (IOException e) { + CPlugin.log(e); + } finally { + gc.dispose(); + } + return null; + } + + private int getHoverWidth(Display display) { + Rectangle displayBounds= display.getBounds(); + int hoverWidth= displayBounds.width - (display.getCursorLocation().x - displayBounds.x); + hoverWidth-= 12; // XXX: Add some space to the border, Revisit + if (hoverWidth < 200) { + hoverWidth= 200; + } + return hoverWidth; + } + + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java new file mode 100644 index 00000000000..3f14415e903 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CAutoIndentStrategy.java @@ -0,0 +1,225 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultAutoIndentStrategy; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IDocument; + + +import org.eclipse.cdt.internal.ui.CPlugin; + +/** + * Auto indent strategy sensitive to brackets. + */ +public class CAutoIndentStrategy extends DefaultAutoIndentStrategy { + + + public CAutoIndentStrategy() { + } + + // evaluate the line with the opening bracket that matches the closing bracket on the given line + protected int findMatchingOpenBracket(IDocument d, int line, int end, int closingBracketIncrease) throws BadLocationException { + + + int start= d.getLineOffset(line); + int brackcount= getBracketCount(d, start, end, false) - closingBracketIncrease; + + + // sum up the brackets counts of each line (closing brackets count negative, + // opening positive) until we find a line the brings the count to zero + while (brackcount < 0) { + line--; + if (line < 0) { + return -1; + } + start= d.getLineOffset(line); + end= start + d.getLineLength(line) - 1; + brackcount += getBracketCount(d, start, end, false); + } + return line; + } + + + private int getBracketCount(IDocument d, int start, int end, boolean ignoreCloseBrackets) throws BadLocationException { + int bracketcount= 0; + while (start < end) { + char curr= d.getChar(start); + start++; + switch (curr) { + case '/' : + if (start < end) { + char next= d.getChar(start); + if (next == '*') { + // a comment starts, advance to the comment end + start= getCommentEnd(d, start + 1, end); + } else if (next == '/') { + // '//'-comment: nothing to do anymore on this line + start= end; + } + } + break; + case '*' : + if (start < end) { + char next= d.getChar(start); + if (next == '/') { + // we have been in a comment: forget what we read before + bracketcount= 0; + start++; + } + } + break; + case '{' : + bracketcount++; + ignoreCloseBrackets= false; + break; + case '}' : + if (!ignoreCloseBrackets) { + bracketcount--; + } + break; + case '"' : + case '\'' : + start= getStringEnd(d, start, end, curr); + break; + default : + } + } + return bracketcount; + } + + // ----------- bracket counting ------------------------------------------------------ + + + private int getCommentEnd(IDocument d, int pos, int end) throws BadLocationException { + while (pos < end) { + char curr= d.getChar(pos); + pos++; + if (curr == '*') { + if (pos < end && d.getChar(pos) == '/') { + return pos + 1; + } + } + } + return end; + } + + protected String getIndentOfLine(IDocument d, int line) throws BadLocationException { + if (line > -1) { + int start= d.getLineOffset(line); + int end= start + d.getLineLength(line) - 1; + int whiteend= findEndOfWhiteSpace(d, start, end); + return d.get(start, whiteend - start); + } else { + return ""; + } + } + + private int getStringEnd(IDocument d, int pos, int end, char ch) throws BadLocationException { + while (pos < end) { + char curr= d.getChar(pos); + pos++; + if (curr == '\\') { + // ignore escaped characters + pos++; + } else if (curr == ch) { + return pos; + } + } + return end; + } + + protected void smartInsertAfterBracket(IDocument d, DocumentCommand c) { + if (c.offset == -1 || d.getLength() == 0) + return; + + try { + int p= (c.offset == d.getLength() ? c.offset - 1 : c.offset); + int line= d.getLineOfOffset(p); + int start= d.getLineOffset(line); + int whiteend= findEndOfWhiteSpace(d, start, c.offset); + + + // shift only when line does not contain any text up to the closing bracket + if (whiteend == c.offset) { + // evaluate the line with the opening bracket that matches out closing bracket + int indLine= findMatchingOpenBracket(d, line, c.offset, 1); + if (indLine != -1 && indLine != line) { + // take the indent of the found line + StringBuffer replaceText= new StringBuffer(getIndentOfLine(d, indLine)); + // add the rest of the current line including the just added close bracket + replaceText.append(d.get(whiteend, c.offset - whiteend)); + replaceText.append(c.text); + // modify document command + c.length= c.offset - start; + c.offset= start; + c.text= replaceText.toString(); + } + } + } catch (BadLocationException excp) { + CPlugin.log(excp); + } + } + + protected void smartIndentAfterNewLine(IDocument d, DocumentCommand c) { + int docLength= d.getLength(); + if (c.offset == -1 || docLength == 0) + return; + + try { + int p= (c.offset == docLength ? c.offset - 1 : c.offset); + int line= d.getLineOfOffset(p); + + + StringBuffer buf= new StringBuffer(c.text); + if (c.offset < docLength && d.getChar(c.offset) == '}') { + int indLine= findMatchingOpenBracket(d, line, c.offset, 0); + if (indLine == -1) { + indLine= line; + } + buf.append(getIndentOfLine(d, indLine)); + } else { + int start= d.getLineOffset(line); + int whiteend= findEndOfWhiteSpace(d, start, c.offset); + buf.append(d.get(start, whiteend - start)); + if (getBracketCount(d, start, c.offset, true) > 0) { + buf.append('\t'); + } + } + c.text= buf.toString(); + + + } catch (BadLocationException excp) { + CPlugin.log(excp); + } + } + + /** + * Returns whether the text ends with one of the given search strings. + */ + private boolean endsWithDelimiter(IDocument d, String txt) { + String[] delimiters= d.getLegalLineDelimiters(); + + for (int i= 0; i < delimiters.length; i++) { + if (txt.endsWith(delimiters[i])) + return true; + } + return false; + } + + + /** + * @see IAutoIndentStrategy#customizeDocumentCommand + */ + public void customizeDocumentCommand(IDocument d, DocumentCommand c) { + if (c.length == 0 && c.text != null && endsWithDelimiter(d, c.text)) + smartIndentAfterNewLine(d, c); + else if ("}".equals(c.text)) { + smartInsertAfterBracket(d, c); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeReader.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeReader.java new file mode 100644 index 00000000000..13de07bfd48 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeReader.java @@ -0,0 +1,230 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + +/** + * Reads from a document either forwards or backwards. May be configured to + * skip comments and strings. + */ +public class CCodeReader extends SingleCharReader { + + /** The EOF character */ + public static final int EOF= -1; + + private boolean fSkipComments= false; + private boolean fSkipStrings= false; + private boolean fForward= false; + + private IDocument fDocument; + private int fOffset; + + private int fEnd= -1; + private int fCachedLineNumber= -1; + private int fCachedLineOffset= -1; + + + public CCodeReader() { + } + + /** + * Returns the offset of the last read character. Should only be called after read has been called. + */ + public int getOffset() { + return fForward ? fOffset -1 : fOffset; + } + + public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException { + fDocument= document; + fOffset= offset; + fSkipComments= skipComments; + fSkipStrings= skipStrings; + + fForward= true; + fEnd= Math.min(fDocument.getLength(), fOffset + length); + } + + public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException { + fDocument= document; + fOffset= offset; + fSkipComments= skipComments; + fSkipStrings= skipStrings; + + fForward= false; + try { + fCachedLineNumber= fDocument.getLineOfOffset(fOffset); + } catch (BadLocationException x) { + throw new IOException(x.getMessage()); + } + } + + /* + * @see Reader#close() + */ + public void close() throws IOException { + fDocument= null; + } + + /* + * @see SingleCharReader#read() + */ + public int read() throws IOException { + try { + return fForward ? readForwards() : readBackwards(); + } catch (BadLocationException x) { + throw new IOException(x.getMessage()); + } + } + + private void gotoCommentEnd() throws BadLocationException { + while (fOffset < fEnd) { + char current= fDocument.getChar(fOffset++); + if (current == '*') { + if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') { + ++ fOffset; + return; + } + } + } + } + + private void gotoStringEnd(char delimiter) throws BadLocationException { + while (fOffset < fEnd) { + char current= fDocument.getChar(fOffset++); + if (current == '\\') { + // ignore escaped characters + ++ fOffset; + } else if (current == delimiter) { + return; + } + } + } + + private void gotoLineEnd() throws BadLocationException { + int line= fDocument.getLineOfOffset(fOffset); + fOffset= fDocument.getLineOffset(line + 1); + } + + private int readForwards() throws BadLocationException { + while (fOffset < fEnd) { + char current= fDocument.getChar(fOffset++); + + switch (current) { + case '/': + + if (fSkipComments && fOffset < fEnd) { + char next= fDocument.getChar(fOffset); + if (next == '*') { + // a comment starts, advance to the comment end + ++ fOffset; + gotoCommentEnd(); + continue; + } else if (next == '/') { + // '//'-comment starts, advance to the line end + gotoLineEnd(); + continue; + } + } + + return current; + + case '"': + case '\'': + + if (fSkipStrings) { + gotoStringEnd(current); + continue; + } + + return current; + } + + return current; + } + + return EOF; + } + + private void handleSingleLineComment() throws BadLocationException { + int line= fDocument.getLineOfOffset(fOffset); + if (line < fCachedLineNumber) { + fCachedLineNumber= line; + fCachedLineOffset= fDocument.getLineOffset(line); + int offset= fOffset; + while (fCachedLineOffset < offset) { + char current= fDocument.getChar(offset--); + if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') { + fOffset= offset; + return; + } + } + } + } + + private void gotoCommentStart() throws BadLocationException { + while (0 < fOffset) { + char current= fDocument.getChar(fOffset--); + if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/') + return; + } + } + + private void gotoStringStart(char delimiter) throws BadLocationException { + while (0 < fOffset) { + char current= fDocument.getChar(fOffset); + if (current == delimiter) { + if ( !(0 <= fOffset && fDocument.getChar(fOffset -1) == '\\')) + return; + } + -- fOffset; + } + } + + private int readBackwards() throws BadLocationException { + + while (0 < fOffset) { + -- fOffset; + + handleSingleLineComment(); + + char current= fDocument.getChar(fOffset); + switch (current) { + case '/': + + if (fSkipComments && fOffset > 1) { + char next= fDocument.getChar(fOffset - 1); + if (next == '*') { + // a comment ends, advance to the comment start + fOffset -= 2; + gotoCommentStart(); + continue; + } + } + + return current; + + case '"': + case '\'': + + if (fSkipStrings) { + -- fOffset; + gotoStringStart(current); + continue; + } + + return current; + } + + return current; + } + + return EOF; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java new file mode 100644 index 00000000000..580cdb61ba5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCodeScanner.java @@ -0,0 +1,257 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import org.eclipse.cdt.internal.ui.text.util.CWordDetector; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import java.util.Map; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.PatternRule; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * A C code scanner. + */ +public final class CCodeScanner extends AbstractCScanner { + + private class CWordRule implements IRule { + + protected static final int UNDEFINED= -1; + + /** The word detector used by this rule */ + protected IWordDetector fDetector; + /** The default token to be returned on success and if nothing else has been specified. */ + protected IToken fDefaultToken; + /** The column constraint */ + protected int fColumn= UNDEFINED; + /** The table of predefined words and token for this rule */ + protected Map fWords= new HashMap(); + + private StringBuffer fBuffer= new StringBuffer(); + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the scanner + * will be rolled back and an undefined token will be returned in order to allow + * any subsequent rules to analyze the characters. + * + * @param detector the word detector to be used by this rule, may not be null + * + * @see #addWord + */ + public CWordRule(IWordDetector detector) { + this(detector, Token.UNDEFINED); + } + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the + * specified default token will be returned. + * + * @param detector the word detector to be used by this rule, may not be null + * @param defaultToken the default token to be returned on success + * if nothing else is specified, may not be null + * + * @see #addWord + */ + public CWordRule(IWordDetector detector, IToken defaultToken) { + + Assert.isNotNull(detector); + Assert.isNotNull(defaultToken); + + fDetector= detector; + fDefaultToken= defaultToken; + } + /** + * Adds a word and the token to be returned if it is detected. + * + * @param word the word this rule will search for, may not be null + * @param token the token to be returned if the word has been found, may not be null + */ + public void addWord(String word, IToken token) { + Assert.isNotNull(word); + Assert.isNotNull(token); + + fWords.put(word, token); + } + /* + * @see IRule#evaluate + */ + public IToken evaluate(ICharacterScanner scanner) { + + int c= scanner.read(); + if (Character.isJavaIdentifierStart((char) c) || (c == '#' && scanner.getColumn() == 1)) { + fBuffer.setLength(0); + do { + fBuffer.append((char) c); + c= scanner.read(); + } while (Character.isJavaIdentifierPart((char) c)); + scanner.unread(); + + IToken token= (IToken) fWords.get(fBuffer.toString()); + if (token != null) + return token; + + //if (fDefaultToken.isUndefined()) + // unreadBuffer(scanner); + + return fDefaultToken; + } + + scanner.unread(); + return Token.UNDEFINED; + } + /** + * Sets a column constraint for this rule. If set, the rule's token + * will only be returned if the pattern is detected starting at the + * specified column. If the column is smaller then 0, the column + * constraint is considered removed. + * + * @param column the column in which the pattern starts + */ + public void setColumnConstraint(int column) { + if (column < 0) + column= UNDEFINED; + fColumn= column; + } + /** + * Returns the characters in the buffer to the scanner. + * + * @param scanner the scanner to be used + */ + protected void unreadBuffer(ICharacterScanner scanner) { + for (int i= fBuffer.length() - 1; i >= 0; i--) + scanner.unread(); + } + }; + + private static String[] fgKeywords= { + "asm", "auto", + "break", + "case", + "const", "continue", + "default", "do", + "else", "enum", "extern", + "for", + "goto", + "if", "inline", + "register", "return", "restrict", + "sizeof", "static", "struct", "switch", + "typedef", + "union", + "volatile", + "while", "_Pragma" + }; + + + private static String[] fgTypes= { "char", "double", "float", "int", "long", "short", "signed", "unsigned", "void", "_Bool", "_Complex", "_Imaginary"}; + private static String[] fgConstants= { "NULL", "__DATE__", "__LINE__", "__TIME__", "__FILE__", "__STDC__"}; + private static String[] fgPreprocessor= { "#define", "#include", "#error", "#pragma", "#ifdef", "#ifndef", "#if", "#else", "#elif", "#endif", "#line"}; + + + private static String[] fgTokenProperties= { + ICColorConstants.C_KEYWORD, + ICColorConstants.C_TYPE, + ICColorConstants.C_STRING, + ICColorConstants.C_DEFAULT + }; + + + /** + * Creates a C code scanner + */ + public CCodeScanner(IColorManager manager, IPreferenceStore store) { + super(manager, store); + initialize(); + } + + /* + * @see AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fgTokenProperties; + } + + /* + * @see AbstractCScanner#createRules() + */ + protected List createRules() { + + List rules= new ArrayList(); + + // Add rule for strings + Token token= getToken(ICColorConstants.C_STRING); + // Add rule for strings and character constants. + rules.add(new SingleLineRule("'", "'", token, '\\')); + + + + // Add generic whitespace rule. + //rules.add(new WhitespaceRule(new CWhitespaceDetector())); + + + // Add word rule for keywords, types, and constants. + token= getToken(ICColorConstants.C_DEFAULT); + CWordRule wordRule= new CWordRule(new CWordDetector(), token); + + token= getToken(ICColorConstants.C_KEYWORD); + for (int i=0; i= start) { // 1GEYL1R: ITPJUI:ALL - java doc edit smartness not work for class comments + // append to input + buf.append(d.get(start, end - start)); + if (end < c.offset) { + if (d.getChar(end) == '/') { + // javadoc started on this line + buf.append(" * "); //$NON-NLS-1$ + } else if (d.getChar(end) == '*') { + buf.append("* "); //$NON-NLS-1$ + } + } + } + + + c.text= buf.toString(); + + } catch (BadLocationException excp) { + // stop work + } + } + + protected void jdocIndentForCommentEnd(IDocument d, DocumentCommand c) { + if (c.offset < 2 || d.getLength() == 0) { + return; + } + try { + if ("* ".equals(d.get(c.offset - 2, 2))) { //$NON-NLS-1$ + // modify document command + c.length++; + c.offset--; + } + } catch (BadLocationException excp) { + // stop work + } + } + + /* + * @see IAutoIndentStrategy#customizeDocumentCommand + */ + public void customizeDocumentCommand(IDocument d, DocumentCommand c) { + if (c.length == 0 && c.text != null && endsWithDelimiter(d, c.text)) + jdocIndentAfterNewLine(d, c); + else if ("/".equals(c.text)) { //$NON-NLS-1$ + jdocIndentForCommentEnd(d, c); + } + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java new file mode 100644 index 00000000000..f679c47c471 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java @@ -0,0 +1,363 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.core.index.IndexModel; +import org.eclipse.cdt.core.index.TagFlags; +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.ContextTypeRegistry; +import org.eclipse.cdt.internal.ui.CCompletionContributorManager; +import org.eclipse.cdt.internal.ui.CElementLabelProvider; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.template.TemplateEngine; +import org.eclipse.cdt.ui.IFunctionSummary; +import java.util.ArrayList; +import java.util.Arrays; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; + +/** + * C completion processor. + */ +public class CCompletionProcessor implements IContentAssistProcessor { + + private CEditor fEditor; + private char[] fProposalAutoActivationSet; + private CCompletionProposalComparator fComparator; + private TemplateEngine fTemplateEngine; + + private boolean fRestrictToMatchingCase; + private boolean fAllowAddIncludes; + + private CElementLabelProvider fElementLabelProvider; + //private ImageRegistry fImageRegistry; + + + public CCompletionProcessor(IEditorPart editor) { + fEditor= (CEditor)editor; + ContextType contextType= ContextTypeRegistry.getInstance().getContextType("C"); //$NON-NLS-1$ + if (contextType != null) + fTemplateEngine= new TemplateEngine(contextType); + fRestrictToMatchingCase= false; + fAllowAddIncludes= true; + + fComparator= new CCompletionProposalComparator(); + + fElementLabelProvider = new CElementLabelProvider(); + //fImageRegistry= CPlugin.getDefault().getImageRegistry(); + } + + /** + * Tells this processor to order the proposals alphabetically. + * + * @param order true if proposals should be ordered. + */ + public void orderProposalsAlphabetically(boolean order) { + fComparator.setOrderAlphabetically(order); + } + + /** + * @see IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return null; + } + + /** + * @see IContentAssistProcessor#getContextInformationValidator() + */ + public IContextInformationValidator getContextInformationValidator() { + return null; + } + + /** + * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters() + */ + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + /** + * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return fProposalAutoActivationSet; + } + + /** + * Sets this processor's set of characters triggering the activation of the + * completion proposal computation. + * + * @param activationSet the activation set + */ + public void setCompletionProposalAutoActivationCharacters(char[] activationSet) { + fProposalAutoActivationSet= activationSet; + } + + /** + * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int) + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { + return null; + } + + /** + * Tells this processor to restrict is proposals to those + * starting with matching cases. + * + * @param restrict true if proposals should be restricted + */ + public void restrictProposalsToMatchingCases(boolean restrict) { + // not yet supported + } + + /** + * Tells this processor to add include statement for proposals that have + * a fully qualified type name + * + * @param restrict true if import can be added + */ + public void allowAddingIncludes(boolean allowAddingIncludes) { + fAllowAddIncludes= allowAddingIncludes; + } + + /** + * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) + */ + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { + //IDocument unit= fManager.getWorkingCopy(fEditor.getEditorInput()); + IDocument document= viewer.getDocument(); + + ICCompletionProposal[] results = null; + + try { + if (document != null) { + + int offset= documentOffset; + int length= 0; + + Point selection= viewer.getSelectedRange(); + if (selection.y > 0) { + offset= selection.x; + length= selection.y; + } + + //CCompletionEvaluator evaluator= new CCompletionEvaluator(document, offset, length); + //evaluator.restrictProposalsToMatchingCases(fRestrictToMatchingCase); + results= evalProposals(document, offset, length); + } + } catch (Exception e) { + CPlugin.log(e); + } + + if(results == null) + results = new ICCompletionProposal[0]; + + if (fTemplateEngine != null) { + try { + fTemplateEngine.reset(); + fTemplateEngine.complete(viewer, documentOffset, null); + } catch (Exception x) { + System.out.println("Template Exception"); + CPlugin.log(x); + } + + ICCompletionProposal[] templateResults= fTemplateEngine.getResults(); + if (results.length == 0) { + results= templateResults; + } else { + // concatenate arrays + ICCompletionProposal[] total= new ICCompletionProposal[results.length + templateResults.length]; + System.arraycopy(templateResults, 0, total, 0, templateResults.length); + System.arraycopy(results, 0, total, templateResults.length, results.length); + results= total; + } + } + + /* + * Order here and not in result collector to make sure that the order + * applies to all proposals and not just those of the compilation unit. + */ + order(results); + if((results.length == 1) && (CPlugin.getDefault().getPreferenceStore().getBoolean(ContentAssistPreference.AUTOINSERT))) { + results[0].apply(document); + // Trick the content assistant into thinking we have no proposals + return new ICCompletionProposal[0]; + } else { + return results; + } + } + + /** + * Order the given proposals. + */ + private ICCompletionProposal[] order(ICCompletionProposal[] proposals) { + Arrays.sort(proposals, fComparator); + return proposals; + } + + /** + * Evaluate the actual proposals for C + */ + private ICCompletionProposal[] evalProposals(IDocument document, int pos, int length) { + IRegion region; + String frag = ""; + + // First, check if we're on a space or trying to open a struct/union + if (pos > 2) { + try { + // If we're on a space and the previous character is valid text, + // parse the previous word. + if (!Character.isJavaIdentifierPart(document.getChar(pos))) { + pos--; + if (!Character.isJavaIdentifierPart(document.getChar(pos))) { + // Comment out the dereference code, only useful once we can + // know variable types to go fish back structure members + //if (document.getChar(offset) == '.') { + // isDereference = true; + // offset--; + //} else if ((document.getChar(offset) == '>') && (document.getChar(offset - 1) == '-')) { + // isDereference = true; + // offset -= 2; + //} + } + } + } catch (Exception e) { + return null; + } + } + + // Get the current "word" + region = CWordFinder.findWord(document, pos); + + // If we're currently + try { + frag = document.get(region.getOffset(), region.getLength()); + frag = frag.trim(); + if (frag.length() == 0) + // No word is selected... + return null; + } catch (BadLocationException x) { + // ignore + return null; + } + // Based on the frag name, build a list of completion proposals + // We look in two places: the content outline and the libs + + + ArrayList completions = new ArrayList(); + + // Look in index manager + IndexModel model = IndexModel.getDefault(); + IProject project = null; + IEditorInput input = fEditor.getEditorInput(); + if(input instanceof IFileEditorInput) { + project = ((IFileEditorInput)input).getFile().getProject(); + + // Bail out quickly, if the project was deleted. + if (!project.exists()) { + project = null; + } + } + if(project != null) { + ITagEntry[] tags= model.query(project, frag+"*", false, false); + if(tags != null && tags.length > 0) { + // We have some matches! + for(int i = 0; i < tags.length; i++) { + + String fname = tags[i].getTagName(); + + int kind = tags[i].getKind(); + + if(kind == TagFlags.T_FUNCTION || kind == TagFlags.T_PROTOTYPE) { + fname = fname + "()"; + } + String proto = fname + " - " + tags[i].getPattern(); + //System.out.println("tagmatch " + fname + " proto " + proto + " type" + tags[i].getKind()); + if(tags[i].getKind() != TagFlags.T_MEMBER) { + completions.add( + new CCompletionProposal( + fname, + region.getOffset(), + region.getLength(), + //fname.length() + 1, + getTagImage(kind), + proto.equals("") ? (fname + "()") : proto, + //null, + //null)); + 3)); + } + } + } + } + + + IFunctionSummary[] summary; + + //UserHelpFunctionInfo inf = plugin.getFunctionInfo(); + summary = CCompletionContributorManager.getDefault().getMatchingFunctions(frag); + if(summary != null) { + for(int i = 0; i < summary.length; i++) { + String fname = summary[i].getName(); + String proto = summary[i].getPrototype(); + completions.add( + new CCompletionProposal( + fname + "()", + region.getOffset(), + region.getLength(), + //fname.length() + 1, + CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION), + proto.equals("") ? (fname + "()") : proto, + //null, + //null)); + 2)); + } + } + return (ICCompletionProposal[]) completions.toArray(new ICCompletionProposal[0]); + } + + private Image getTagImage(int kind) { + switch (kind) { + case TagFlags.T_PROTOTYPE: + return CPluginImages.get(CPluginImages.IMG_OBJS_DECLARATION); + case TagFlags.T_CLASS: + return CPluginImages.get(CPluginImages.IMG_OBJS_CLASS); + case TagFlags.T_ENUM: + case TagFlags.T_VARIABLE: + case TagFlags.T_MEMBER: + return CPluginImages.get(CPluginImages.IMG_OBJS_FIELD); + case TagFlags.T_FUNCTION: + return CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION); + case TagFlags.T_STRUCT: + return CPluginImages.get(CPluginImages.IMG_OBJS_STRUCT); + case TagFlags.T_UNION: + return CPluginImages.get(CPluginImages.IMG_OBJS_UNION); + case TagFlags.T_MACRO: + return CPluginImages.get(CPluginImages.IMG_OBJS_MACRO); + } + return CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposal.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposal.java new file mode 100644 index 00000000000..82a8705851b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposal.java @@ -0,0 +1,346 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.util.Assert; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; + + +public class CCompletionProposal implements ICCompletionProposal { + private String fDisplayString; + private String fReplacementString; + private int fReplacementOffset; + private int fReplacementLength; + private int fCursorPosition; + private Image fImage; + private IContextInformation fContextInformation; + private int fContextInformationPosition; + //private ProposalInfo fProposalInfo; + //private IImportDeclaration fImportDeclaration; + private char[] fTriggerCharacters; + + private int fRelevance; + + /** + * Creates a new completion proposal. All fields are initialized based on the provided information. + * + * @param replacementString the actual string to be inserted into the document + * @param replacementOffset the offset of the text to be replaced + * @param replacementLength the length of the text to be replaced + * @param image the image to display for this proposal + * @param displayString the string to be displayed for the proposal + * If set to null, the replacement string will be taken as display string. + */ + public CCompletionProposal(String replacementString, int replacementOffset, int replacementLength, Image image, String displayString, int relevance) { + Assert.isNotNull(replacementString); + Assert.isTrue(replacementOffset >= 0); + Assert.isTrue(replacementLength >= 0); + + fReplacementString= replacementString; + fReplacementOffset= replacementOffset; + fReplacementLength= replacementLength; + fImage= image; + fDisplayString= displayString != null ? displayString : replacementString; + fRelevance= relevance; + + fCursorPosition= replacementString.length(); + + fContextInformation= null; + fContextInformationPosition= -1; + //fIncludeDeclaration= null; + fTriggerCharacters= null; + //fProposalInfo= null; + } + + /** + * Sets the context information. + * @param contentInformation The context information associated with this proposal + */ + public void setContextInformation(IContextInformation contextInformation) { + fContextInformation= contextInformation; + fContextInformationPosition= (fContextInformation != null ? fCursorPosition : -1); + } + + /** + * Sets the import declaration to import when applied. + * @param importDeclaration Optional import declaration to be added. Can be null. The underlying compilation unit + * is assumed to be compatible with the document passed in apply. + * + public void setIncludeDeclaration(IImportDeclaration importDeclaration) { + fIncludeDeclaration= importDeclaration; + } */ + + /** + * Sets the trigger characters. + * @param triggerCharacters The set of characters which can trigger the application of this completion proposal + */ + public void setTriggerCharacters(char[] triggerCharacters) { + fTriggerCharacters= triggerCharacters; + } + + /** + * Sets the proposal info. + * @param additionalProposalInfo The additional information associated with this proposal or null + * + public void setProposalInfo(ProposalInfo proposalInfo) { + fProposalInfo= proposalInfo; + }*/ + + /** + * Sets the cursor position relative to the insertion offset. By default this is the length of the completion string + * (Cursor positioned after the completion) + * @param cursorPosition The cursorPosition to set + */ + public void setCursorPosition(int cursorPosition) { + Assert.isTrue(cursorPosition >= 0); + fCursorPosition= cursorPosition; + fContextInformationPosition= (fContextInformation != null ? fCursorPosition : -1); + } + +/* protected void addInclude(IRequiredInclude[] inc, CFileElementWorkingCopy tu) { + AddIncludeOperation op= new AddIncludeOperation(fEditor, tu, inc, false); + try { + ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell()); + dialog.run(false, true, op); + } catch (InvocationTargetException e) { + e.printStackTrace(); + MessageDialog.openError(getShell(), CEditorMessages.getString("AddIncludeOnSelection.error.message1"), e.getTargetException().getMessage()); //$NON-NLS-1$ + } catch (InterruptedException e) { + // Do nothing. Operation has been canceled. + } + } */ + + protected void applyIncludes(IDocument document) { + //AddIncludeOperation(ITextEditor ed, CFileElementWorkingCopy tu, IRequiredInclude[] includes, boolean save) { + + //if (fIncludeDeclaration == null) { + return; + //} + + /* ICompilationUnit cu= (ICompilationUnit) JavaModelUtil.findElementOfKind(fImportDeclaration, IJavaElement.COMPILATION_UNIT); + if (cu != null) { + try { + IType[] types= cu.getTypes(); + if (types.length == 0 || types[0].getSourceRange().getOffset() > fReplacementOffset) { + // do not add import for code assist on import statements + return; + } + + String[] prefOrder= ImportOrganizePreferencePage.getImportOrderPreference(); + int threshold= ImportOrganizePreferencePage.getImportNumberThreshold(); + ImportsStructure impStructure= new ImportsStructure(cu, prefOrder, threshold, true); + + impStructure.addImport(fImportDeclaration.getElementName()); + // will modify the document as the CU works on the document + impStructure.create(false, null); + + } catch (CoreException e) { + JavaPlugin.log(e); + } + } */ + } + + /* + * @see ICompletionProposalExtension#apply(IDocument, char, int) + */ + public void apply(IDocument document, char trigger, int offset) { + try { + + // patch replacement length + int delta= offset - (fReplacementOffset + fReplacementLength); + if (delta > 0) + fReplacementLength += delta; + + if (trigger == (char) 0) { + replace(document, fReplacementOffset, fReplacementLength, fReplacementString); + } else { + StringBuffer buffer= new StringBuffer(fReplacementString); + + // fix for PR #5533. Assumes that no eating takes place. + if ((fCursorPosition > 0 && fCursorPosition <= buffer.length() && buffer.charAt(fCursorPosition - 1) != trigger)) { + buffer.insert(fCursorPosition, trigger); + ++fCursorPosition; + } + + replace(document, fReplacementOffset, fReplacementLength, buffer.toString()); + } + + int oldLen= document.getLength(); + applyIncludes(document); + fReplacementOffset += document.getLength() - oldLen; + + } catch (BadLocationException x) { + // ignore + } + } + + // #6410 - File unchanged but dirtied by code assist + private void replace(IDocument document, int offset, int length, String string) throws BadLocationException { + if (!document.get(offset, length).equals(string)) + document.replace(offset, length, string); + } + + /* + * @see ICompletionProposal#apply + */ + public void apply(IDocument document) { + apply(document, (char) 0, fReplacementOffset + fReplacementLength); + } + + /* + * @see ICompletionProposal#getSelection + */ + public Point getSelection(IDocument document) { + return new Point(fReplacementOffset + fCursorPosition, 0); + } + + /* + * @see ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return fContextInformation; + } + + /* + * @see ICompletionProposal#getImage() + */ + public Image getImage() { + return fImage; + } + + /* + * @see ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return fDisplayString; + } + + /* + * @see ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + //if (fProposalInfo != null) { + // return fProposalInfo.getInfo(); + //} + return null; + } + + /* + * @see ICompletionProposalExtension#getTriggerCharacters() + */ + public char[] getTriggerCharacters() { + return fTriggerCharacters; + } + + /* + * @see ICompletionProposalExtension#getContextInformationPosition() + */ + public int getContextInformationPosition() { + return fReplacementOffset + fContextInformationPosition; + } + + /** + * Gets the replacement offset. + * @return Returns a int + */ + public int getReplacementOffset() { + return fReplacementOffset; + } + + /** + * Sets the replacement offset. + * @param replacementOffset The replacement offset to set + */ + public void setReplacementOffset(int replacementOffset) { + Assert.isTrue(replacementOffset >= 0); + fReplacementOffset= replacementOffset; + } + + /** + * Gets the replacement length. + * @return Returns a int + */ + public int getReplacementLength() { + return fReplacementLength; + } + + /** + * Sets the replacement length. + * @param replacementLength The replacementLength to set + */ + public void setReplacementLength(int replacementLength) { + Assert.isTrue(replacementLength >= 0); + fReplacementLength= replacementLength; + } + + /** + * Gets the replacement string. + * @return Returns a String + */ + public String getReplacementString() { + return fReplacementString; + } + + /** + * Sets the replacement string. + * @param replacementString The replacement string to set + */ + public void setReplacementString(String replacementString) { + fReplacementString= replacementString; + } + + /** + * Sets the image. + * @param image The image to set + */ + public void setImage(Image image) { + fImage= image; + } + + /* + * @see ICompletionProposalExtension#isValidFor(IDocument, int) + */ + public boolean isValidFor(IDocument document, int offset) { + + if (offset < fReplacementOffset) + return false; + + int replacementLength= fReplacementString == null ? 0 : fReplacementString.length(); + if (offset >= fReplacementOffset + replacementLength) + return false; + + try { + int length= offset - fReplacementOffset; + String start= document.get(fReplacementOffset, length); + return fReplacementString.substring(0, length).equalsIgnoreCase(start); + } catch (BadLocationException x) { + } + + return false; + } + + /** + * Gets the proposal's relevance. + * @return Returns a int + */ + public int getRelevance() { + return fRelevance; + } + + /** + * Sets the proposal's relevance. + * @param relevance The relevance to set + */ + public void setRelevance(int relevance) { + fRelevance= relevance; + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposalComparator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposalComparator.java new file mode 100644 index 00000000000..cc7fc40ca14 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCompletionProposalComparator.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.Comparator; + +public class CCompletionProposalComparator implements Comparator { + + private boolean fOrderAlphabetically; + + /** + * Constructor for CompletionProposalComparator. + */ + public CCompletionProposalComparator() { + fOrderAlphabetically= false; + } + + public void setOrderAlphabetically(boolean orderAlphabetically) { + fOrderAlphabetically= orderAlphabetically; + } + + /* (non-Javadoc) + * @see Comparator#compare(Object, Object) + */ + public int compare(Object o1, Object o2) { + ICCompletionProposal c1= (ICCompletionProposal) o1; + ICCompletionProposal c2= (ICCompletionProposal) o2; + if (!fOrderAlphabetically) { + int relevanceDif= c2.getRelevance() - c1.getRelevance(); + if (relevanceDif != 0) { + return relevanceDif; + } + } + return c1.getDisplayString().compareToIgnoreCase(c2.getDisplayString()); + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java new file mode 100644 index 00000000000..0ea6dd1075d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java @@ -0,0 +1,213 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextViewer; + +/** + * Double click strategy aware of C identifier syntax rules. + */ +public class CDoubleClickSelector implements ITextDoubleClickStrategy { + + protected ITextViewer fText; + protected int fPos; + protected int fStartPos; + protected int fEndPos; + + + protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '"', '"'}; + + public CDoubleClickSelector() { + super(); + } + + + /** + * @see ITextDoubleClickStrategy#doubleClicked + */ + public void doubleClicked(ITextViewer text) { + fPos= text.getSelectedRange().x; + + + if (fPos < 0) + return; + + + fText= text; + + + if (!selectBracketBlock()) + selectWord(); + } + + + protected boolean matchBracketsAt() { + char prevChar, nextChar; + + + int i; + int bracketIndex1= fgBrackets.length; + int bracketIndex2= fgBrackets.length; + + + fStartPos= -1; + fEndPos= -1; + + // get the chars preceding and following the start position + try { + IDocument doc= fText.getDocument(); + + + prevChar= doc.getChar(fPos - 1); + nextChar= doc.getChar(fPos); + + + // is the char either an open or close bracket? + for (i= 0; i < fgBrackets.length; i= i + 2) { + if (prevChar == fgBrackets[i]) { + fStartPos= fPos - 1; + bracketIndex1= i; + } + } + for (i= 1; i < fgBrackets.length; i= i + 2) { + if (nextChar == fgBrackets[i]) { + fEndPos= fPos; + bracketIndex2= i; + } + } + + + if (fStartPos > -1 && bracketIndex1 < bracketIndex2) { + fEndPos= searchForClosingBracket(fStartPos, prevChar, fgBrackets[bracketIndex1 + 1], doc); + if (fEndPos > -1) + return true; + else + fStartPos= -1; + } else if (fEndPos > -1) { + fStartPos= searchForOpenBracket(fEndPos, fgBrackets[bracketIndex2 - 1], nextChar, doc); + if (fStartPos > -1) + return true; + else + fEndPos= -1; + } + } catch (BadLocationException x) { + } + + + return false; + } + + + protected boolean matchWord() { + IDocument doc= fText.getDocument(); + try { + int pos= fPos; + char c; + + + while (pos >= 0) { + c= doc.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + --pos; + } + fStartPos= pos; + + + pos= fPos; + int length= doc.getLength(); + + + while (pos < length) { + c= doc.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + ++pos; + } + fEndPos= pos; + + + return true; + + + } catch (BadLocationException x) { + } + return false; + } + + + protected int searchForClosingBracket(int startPos, char openBracket, char closeBracket, IDocument doc) throws BadLocationException { + int stack= 1; + int closePos= startPos + 1; + int length= doc.getLength(); + char nextChar; + + + while (closePos < length && stack > 0) { + nextChar= doc.getChar(closePos); + if (nextChar == openBracket && nextChar != closeBracket) + stack++; + else if (nextChar == closeBracket) + stack--; + closePos++; + } + + + if (stack == 0) + return closePos - 1; + else + return -1; + } + + + protected int searchForOpenBracket(int startPos, char openBracket, char closeBracket, IDocument doc) throws BadLocationException { + int stack= 1; + int openPos= startPos - 1; + char nextChar; + + while (openPos >= 0 && stack > 0) { + nextChar= doc.getChar(openPos); + if (nextChar == closeBracket && nextChar != openBracket) + stack++; + else if (nextChar == openBracket) + stack--; + openPos--; + } + + + if (stack == 0) + return openPos + 1; + else + return -1; + } + + + protected boolean selectBracketBlock() { + if (matchBracketsAt()) { + if (fStartPos == fEndPos) + fText.setSelectedRange(fStartPos, 0); + else + fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); + + + return true; + } + return false; + } + + + protected void selectWord() { + if (matchWord()) { + if (fStartPos == fEndPos) + fText.setSelectedRange(fStartPos, 0); + else + fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java new file mode 100644 index 00000000000..97270dcdd9d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CFormattingStrategy.java @@ -0,0 +1,83 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.formatter.IFormattingStrategy; +import org.eclipse.jface.text.source.ISourceViewer; + + +import org.eclipse.cdt.internal.formatter.CCodeFormatter; + + +public class CFormattingStrategy implements IFormattingStrategy { + + + private String fInitialIndentation; + private ISourceViewer fViewer; + + + public CFormattingStrategy(ISourceViewer viewer) { + fViewer = viewer; + } + /** + * @see IFormattingStrategy#format(String, boolean, String, int[]) + */ + public String format(String content, boolean isLineStart, String indentation, int[] positions) { + //ConfigurableOption[] options= CPlugin.getDefault().getCodeFormatterOptions(); + CCodeFormatter formatter= new CCodeFormatter(/* null options */); + + //IDocument doc= fViewer.getDocument(); + //String lineDelimiter= getLineDelimiterFor(doc); + //formatter.options.setLineSeparator(lineDelimiter); + + + //formatter.setPositionsToMap(positions); + return formatter.formatSourceString(content); + } + /** + * @see IFormattingStrategy#formatterStarts(String) + */ + public void formatterStarts(String initialIndentation) { + fInitialIndentation= initialIndentation; + } + /** + * @see IFormattingStrategy#formatterStops() + */ + public void formatterStops() { + } + + /** + * Embodies the policy which line delimiter to use when inserting into + * a document + */ + private static String getLineDelimiterFor(IDocument doc) { + String lineDelim= null; + try { + lineDelim= doc.getLineDelimiter(0); + } catch (BadLocationException e) { + } + if (lineDelim == null) { + String systemDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + String[] lineDelims= doc.getLegalLineDelimiters(); + for (int i= 0; i < lineDelims.length; i++) { + if (lineDelims[i].equals(systemDelimiter)) { + lineDelim= systemDelimiter; + break; + } + } + if (lineDelim == null) { + lineDelim= lineDelims.length > 0 ? lineDelims[0] : systemDelimiter; + } + } + return lineDelim; + } + + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java new file mode 100644 index 00000000000..fbb554202f1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CMultilineCommentScanner.java @@ -0,0 +1,149 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.util.Assert; + + +/** + * Implementation of IRule for C code scanning. + * Optimized to partition C documents + * Is is capable of detecting a pattern which begins with a given starting + * sequence and ends with a given ending sequence. If the ending sequence is + * not specified, it can be either end of line, end or file, or both. Additionally, + * the pattern can be constrained to begin in a certain column. + */ +public class CMultilineCommentScanner implements IRule { + + protected static final int UNDEFINED= -1; + + /** The token to be returned on success */ + protected IToken fToken; + + /** The pattern's escape character */ + protected char fEscapeCharacter; + /** Indicates whether end of line termines the pattern */ + protected boolean fBreaksOnEOL; + + /** + * Creates a rule for the given starting and ending sequence. + * When these sequences are detected the rule will return the specified token. + * Alternatively, the sequence can also be ended by the end of the line. + * Any character which follows the given escapeCharacter will be ignored. + * + * @param startSequence the pattern's start sequence + * @param endSequence the pattern's end sequence, null is a legal value + * @param token the token which will be returned on success + * @param escapeCharacter any character following this one will be ignored + * @param indicates whether the end of the line also termines the pattern + */ + public CMultilineCommentScanner(IToken token, char escapeCharacter, boolean breaksOnEOL) { + Assert.isNotNull(token); + + fToken= token; + fEscapeCharacter= escapeCharacter; + fBreaksOnEOL= breaksOnEOL; + } + + /** + * Returns whether the end sequence was detected. As the pattern can be considered + * ended by a line delimiter, the result of this method is true if the + * rule breaks on the end of the line, or if the EOF character is read. + * + * @param scanner the character scanner to be used + * @return true if the end sequence has been detected + */ + protected boolean endSequenceDetected(ICharacterScanner scanner) { + int c; + //char[][] delimiters= scanner.getLegalLineDelimiters(); + while ((c= scanner.read()) != ICharacterScanner.EOF) { + if (c == fEscapeCharacter) { + // Skip the escaped character. + scanner.read(); + } else if (c == '*') { + c = scanner.read(); + if(c == '/') { + return true; + } + scanner.unread(); + // Check if the specified end sequence has been found. + //} else if (fBreaksOnEOL) { + // Check for end of line since it can be used to terminate the pattern. + //for (int i= 0; i < delimiters.length; i++) { + // if (c == delimiters[i][0] && sequenceDetected(scanner, delimiters[i], false)) + // return true; + //} + } + } + scanner.unread(); + return true; + } + /* + * @see IRule#evaluate + */ + public IToken evaluate(ICharacterScanner scanner) { + + int c= scanner.read(); + + if (c == '/') { + if((c= scanner.read()) == '*') { + endSequenceDetected(scanner); + return fToken; + } + scanner.unread(); + } + + scanner.unread(); + return Token.UNDEFINED; + } + /** + * Returns whether the next characters to be read by the character scanner + * are an exact match with the given sequence. No escape characters are allowed + * within the sequence. If specified the sequence is considered to be found + * when reading the EOF character. + * + * @param scanner the character scanner to be used + * @param sequence the sequence to be detected + * @param eofAllowed indicated whether EOF terminates the pattern + * @return true if the given sequence has been detected + */ + protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) { + for (int i= 1; i < sequence.length; i++) { + int c= scanner.read(); + if (c == ICharacterScanner.EOF && eofAllowed) { + return true; + } else if (c != sequence[i]) { + // Non-matching character detected, rewind the scanner back to the start. + scanner.unread(); + for (int j= i-1; j > 0; j--) + scanner.unread(); + return false; + } + } + + return true; + } + /** + * Sets a column constraint for this rule. If set, the rule's token + * will only be returned if the pattern is detected starting at the + * specified column. If the column is smaller then 0, the column + * constraint is considered removed. + * + * @param column the column in which the pattern starts + */ + public void setColumnConstraint(int column) { + if (column < 0) + column= UNDEFINED; + //fColumn= column; + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java new file mode 100644 index 00000000000..e8c8e26fcf1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java @@ -0,0 +1,192 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; + + +/** + * Helper class for match pairs of characters. + */ +public class CPairMatcher { + + + public static final int LEFT= 1; + public static final int RIGHT= 2; + + + + protected char[] fPairs; + protected IDocument fDocument; + protected int fOffset; + + protected int fStartPos; + protected int fEndPos; + protected int fAnchor; + + protected CCodeReader fReader= new CCodeReader(); + + + public CPairMatcher(char[] pairs) { + fPairs= pairs; + } + + public IRegion match(IDocument document, int offset) { + + + fOffset= offset; + + + if (fOffset < 0) + return null; + + + fDocument= document; + + + if (matchPairsAt() && fStartPos != fEndPos) + return new Region(fStartPos, fEndPos - fStartPos + 1); + + return null; + } + + public int getAnchor() { + return fAnchor; + } + + public void dispose() { + fDocument= null; + if (fReader != null) { + try { + fReader.close(); + } catch (IOException x) { + // ignore + } + fReader= null; + } + } + + protected boolean matchPairsAt() { + + + int i; + int pairIndex1= fPairs.length; + int pairIndex2= fPairs.length; + + + fStartPos= -1; + fEndPos= -1; + + + // get the chars preceding and following the start position + try { + + + /* + A quick hack to get around the fact that we can't bracket + match on the very first element of a document. We make the + character to match a null character which is unlikely to match. + */ + char prevChar= (fOffset > 0) ? fDocument.getChar(fOffset - 1) : '\0'; + char nextChar= fDocument.getChar(fOffset); + + + // search for opening peer character next to the activation point + for (i= 0; i < fPairs.length; i= i + 2) { + if (nextChar == fPairs[i]) { + fStartPos= fOffset; + pairIndex1= i; + } else if (prevChar == fPairs[i]) { + fStartPos= fOffset - 1; + pairIndex1= i; + } + } + + // search for closing peer character next to the activation point + for (i= 1; i < fPairs.length; i= i + 2) { + if (prevChar == fPairs[i]) { + fEndPos= fOffset - 1; + pairIndex2= i; + } else if (nextChar == fPairs[i]) { + fEndPos= fOffset; + pairIndex2= i; + } + } + + + if (fEndPos > -1) { + fAnchor= RIGHT; + fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument); + if (fStartPos > -1) + return true; + else + fEndPos= -1; + } else if (fStartPos > -1) { + fAnchor= LEFT; + fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument); + if (fEndPos > -1) + return true; + else + fStartPos= -1; + } + + + } catch (BadLocationException x) { + } catch (IOException x) { + } + + + return false; + } + + protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException { + + fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true); + + int stack= 1; + int c= fReader.read(); + while (c != fReader.EOF) { + if (c == openingPeer && c != closingPeer) + stack++; + else if (c == closingPeer) + stack--; + + if (stack == 0) + return fReader.getOffset(); + + c= fReader.read(); + } + + return -1; + } + + protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException { + + fReader.configureBackwardReader(document, offset, true, true); + + int stack= 1; + int c= fReader.read(); + while (c != fReader.EOF) { + if (c == closingPeer && c != openingPeer) + stack++; + else if (c == openingPeer) + stack--; + + if (stack == 0) + return fReader.getOffset(); + + c= fReader.read(); + } + + return -1; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java new file mode 100644 index 00000000000..196ed1b5e8e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPartitionScanner.java @@ -0,0 +1,102 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + + +import org.eclipse.jface.text.rules.BufferedRuleBasedScanner; +import org.eclipse.jface.text.rules.EndOfLineRule; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.text.rules.Token; + + +/** + * This scanner recognizes comments + */ +public class CPartitionScanner extends BufferedRuleBasedScanner { + + + private final static String SKIP= "__skip"; + + + public final static String C_MULTILINE_COMMENT= "c_multi_line_comment"; + public final static String C_SINGLE_LINE_COMMENT= "c_single_line_comment"; + public final static String C_STRING= "c_string"; + + + /** + * Detector for empty comments. + */ + static class EmptyCommentDetector implements IWordDetector { + + + /** + * @see IWordDetector#isWordStart + */ + public boolean isWordStart(char c) { + return (c == '/'); + } + + + /** + * @see IWordDetector#isWordPart + */ + public boolean isWordPart(char c) { + return (c == '*' || c == '/'); + } + }; + + + /** + * Creates the partitioner and sets up the appropriate rules. + */ + public CPartitionScanner() { + // Set buffer size to 1k + super(1000); + + IToken comment= new Token(C_MULTILINE_COMMENT); + IToken single_comment= new Token(C_SINGLE_LINE_COMMENT); + IToken string= new Token(C_STRING); + IToken skip= new Token(SKIP); + + + + List rules= new ArrayList(); + + + // Minimize the number of rules, since we have duplicate rules + // in the CCodeScanner... + + + // Add rule for single line comments. + rules.add(new EndOfLineRule("//", single_comment)); + + + // Add rule for strings and character constants. + rules.add(new SingleLineRule("\"", "\"", string, '\\')); + rules.add(new SingleLineRule("'", "'", skip, '\\')); + + + // Add special case word rule. + //WordRule wordRule= new WordRule(new EmptyCommentDetector()); + //wordRule.addWord("/**/", comment); + //rules.add(wordRule); + + + // Add rules for multi-line comments. + //rules.add(new MultiLineRule("/*", "*/", comment)); + rules.add(new CMultilineCommentScanner(comment, (char)0, false)); + + IRule[] result= new IRule[rules.size()]; + rules.toArray(result); + setRules(result); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java new file mode 100644 index 00000000000..b394fc6da98 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.editor.CContentOutlinePage; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.reconciler.DirtyRegion; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; + + +public class CReconcilingStrategy implements IReconcilingStrategy { + + + private CContentOutlinePage fOutliner; + private int fLastRegionOffset; + + + public CReconcilingStrategy(CEditor editor) { + fOutliner= editor.getOutlinePage(); + fLastRegionOffset = Integer.MAX_VALUE; + } + + /** + * @see IReconcilingStrategy#reconcile(document) + */ + public void setDocument(IDocument document) { + } + + + /** + * @see IReconcilingStrategy#reconcile(region) + */ + public void reconcile(IRegion region) { + // We use a trick to avoid running the reconciler multiple times + // on a file when it gets changed. This is because this gets called + // multiple times with different regions of the file, we do a + // complete parse on the first region. + if(region.getOffset() <= fLastRegionOffset) { + reconcile(); + } + fLastRegionOffset = region.getOffset(); + } + + + /** + * @see IReconcilingStrategy#reconcile(dirtyRegion, region) + */ + public void reconcile(DirtyRegion dirtyRegion, IRegion region) { + // FIXME: This seems to generate to much flashing in + // the contentouline viewer. + //reconcile(); + } + + private void reconcile() { + fOutliner.contentUpdated(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java new file mode 100644 index 00000000000..545ee9176b5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -0,0 +1,347 @@ +package org.eclipse.cdt.internal.ui.text; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.HashMap; +import java.util.Vector; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IPluginRegistry; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.IAutoIndentStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.formatter.ContentFormatter; +import org.eclipse.jface.text.formatter.IContentFormatter; +import org.eclipse.jface.text.formatter.IFormattingStrategy; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.reconciler.IReconciler; +import org.eclipse.jface.text.reconciler.Reconciler; +import org.eclipse.jface.text.rules.RuleBasedPartitioner; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.ui.texteditor.ITextEditor; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.CEditorTextHoverDispatcher; +import org.eclipse.cdt.internal.ui.text.eclipse2.CPresentationReconciler; +import org.eclipse.cdt.internal.ui.text.eclipse2.CRuleBasedDamagerRepairer; +import org.eclipse.cdt.ui.ICDTConstants; + + + +/** + * Configuration for an SourceViewer which shows C code. + */ +public class CSourceViewerConfiguration extends SourceViewerConfiguration { + + /** Key used to look up display tab width */ + public final static String PREFERENCE_TAB_WIDTH= "org.eclipse.cdt.editor.tab.width"; //$NON-NLS-1$ + /** Key used to look up code formatter tab size */ + private final static String CODE_FORMATTER_TAB_SIZE= "org.eclipse.cdt.formatter.tabulation.size"; //$NON-NLS-1$ + /** Key used to look up code formatter tab character */ + private final static String CODE_FORMATTER_TAB_CHAR= "org.eclipse.cdt.formatter.tabulation.char"; //$NON-NLS-1$ + + private CTextTools fTextTools; + private CEditor fEditor; + + /** + * Creates a new C source viewer configuration for viewers in the given editor using + * the given C tools collection. + * + * @param tools the C text tools collection to be used + * @param editor the editor in which the configured viewer will reside + */ + public CSourceViewerConfiguration(CTextTools tools, CEditor editor) { + fTextTools= tools; + fEditor= editor; + } + + /** + * Returns the C multiline comment scanner for this configuration. + * + * @return the C multiline comment scanner + */ + protected RuleBasedScanner getMultilineCommentScanner() { + return fTextTools.getMultilineCommentScanner(); + } + + /** + * Returns the C singleline comment scanner for this configuration. + * + * @return the C singleline comment scanner + */ + protected RuleBasedScanner getSinglelineCommentScanner() { + return fTextTools.getSinglelineCommentScanner(); + } + + /** + * Returns the C string scanner for this configuration. + * + * @return the C string scanner + */ + protected RuleBasedScanner getStringScanner() { + return fTextTools.getStringScanner(); + } + + /** + * Returns the color manager for this configuration. + * + * @return the color manager + */ + protected IColorManager getColorManager() { + return fTextTools.getColorManager(); + } + + /** + * Returns the editor in which the configured viewer(s) will reside. + * + * @return the enclosing editor + */ + protected ITextEditor getEditor() { + return fEditor; + } + + /** + * @see ISourceViewerConfiguration#getPresentationReconciler(ISourceViewer) + */ + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + + CPresentationReconciler reconciler= new CPresentationReconciler(); + + RuleBasedScanner scanner; + + if(sourceViewer instanceof CEditor.AdaptedSourceViewer) { + String language = ((CEditor.AdaptedSourceViewer)sourceViewer).getDisplayLanguage(); + if(language != null && language.equals(CEditor.LANGUAGE_CPP)) { + scanner= fTextTools.getCppCodeScanner(); + } else { + scanner= fTextTools.getCCodeScanner(); + } + } else { + scanner= fTextTools.getCCodeScanner(); + } + + CRuleBasedDamagerRepairer dr= new CRuleBasedDamagerRepairer(scanner); + + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + + //TextAttribute attr = new TextAttribute(manager.getColor(ICColorConstants.C_DEFAULT)); + + dr= new CRuleBasedDamagerRepairer(getSinglelineCommentScanner()); + reconciler.setDamager(dr, CPartitionScanner.C_SINGLE_LINE_COMMENT); + reconciler.setRepairer(dr, CPartitionScanner.C_SINGLE_LINE_COMMENT); + + dr= new CRuleBasedDamagerRepairer(getStringScanner()); + reconciler.setDamager(dr, CPartitionScanner.C_STRING); + reconciler.setRepairer(dr, CPartitionScanner.C_STRING); + + dr= new CRuleBasedDamagerRepairer(getMultilineCommentScanner()); + reconciler.setDamager(dr, CPartitionScanner.C_MULTILINE_COMMENT); + reconciler.setRepairer(dr, CPartitionScanner.C_MULTILINE_COMMENT); + + + return reconciler; + } + + + /** + * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer) + */ + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + ContentAssistant assistant = new ContentAssistant(); + // IFile file = (sourceViewer). + assistant.setContentAssistProcessor(new CCompletionProcessor(fEditor), IDocument.DEFAULT_CONTENT_TYPE); + assistant.enableAutoActivation(true); + assistant.setAutoActivationDelay(500); + assistant.setProposalPopupOrientation(assistant.PROPOSAL_OVERLAY); + return assistant; + } + + /** + * @see SourceViewerConfiguration#getReconciler(ISourceViewer) + */ + public IReconciler getReconciler(ISourceViewer sourceViewer) { + if (fEditor != null && fEditor.isEditable()) { + Reconciler reconciler= new Reconciler(); + reconciler.setDelay(1000); + reconciler.setIsIncrementalReconciler(false); + reconciler.setReconcilingStrategy(new CReconcilingStrategy(fEditor), IDocument.DEFAULT_CONTENT_TYPE); + return reconciler; + } + return null; + } + + + /** + * @see SourceViewerConfiguration#getAutoIndentStrategy(ISourceViewer, String) + */ + public IAutoIndentStrategy getAutoIndentStrategy(ISourceViewer sourceViewer, String contentType) { + if(CPartitionScanner.C_MULTILINE_COMMENT.equals(contentType)) + return new CCommentAutoIndentStrategy(); + return new CAutoIndentStrategy(); + } + + + /** + * @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String) + */ + public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) { + return new CDoubleClickSelector(); + } + + + /** + * @see SourceViewerConfiguration#getDefaultPrefix(ISourceViewer, String) + */ + public String getDefaultPrefix(ISourceViewer sourceViewer, String contentType) { + if(IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) + return "//"; + if(CPartitionScanner.C_SINGLE_LINE_COMMENT.equals(contentType)) + return "//"; + if(CPartitionScanner.C_MULTILINE_COMMENT.equals(contentType)) + return "//"; + return null; + } + + + /* + * @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String) + */ + public String[] getIndentPrefixes(ISourceViewer sourceViewer, String contentType) { + + Vector vector= new Vector(); + + // prefix[0] is either '\t' or ' ' x tabWidth, depending on useSpaces + int tabWidth= getPreferenceStore().getInt(PREFERENCE_TAB_WIDTH); + boolean useSpaces= getPreferenceStore().getBoolean(CEditor.SPACES_FOR_TABS); //$NON-NLS-1$ + + for (int i= 0; i <= tabWidth; i++) { + StringBuffer prefix= new StringBuffer(); + + if (useSpaces) { + for (int j= 0; j + i < tabWidth; j++) + prefix.append(' '); + + if (i != 0) + prefix.append('\t'); + } else { + for (int j= 0; j < i; j++) + prefix.append(' '); + + if (i != tabWidth) + prefix.append('\t'); + } + + vector.add(prefix.toString()); + } + + vector.add(""); //$NON-NLS-1$ + + return (String[]) vector.toArray(new String[vector.size()]); + } + + + /** + * @see SourceViewerConfiguration#getTabWidth(ISourceViewer) + */ + public int getTabWidth(ISourceViewer sourceViewer) { + return getPreferenceStore().getInt(PREFERENCE_TAB_WIDTH); + } + + + /** + * @see SourceViewerConfiguration#getAnnotationHover(ISourceViewer) + */ + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new CAnnotationHover(); + } + + + /** + * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String) + */ + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + HashMap textHovers = new HashMap( 3 ); + IPluginRegistry pluginRegistry = Platform.getPluginRegistry(); + IExtensionPoint point = pluginRegistry.getExtensionPoint( CPlugin.getDefault().getDescriptor().getUniqueIdentifier(), + ICDTConstants.EP_TEXT_HOVERS ); + if ( point != null ) + { + IExtension[] extensions = point.getExtensions(); + for ( int i = 0; i < extensions.length; i++ ) + { + IExtension currentExtension = extensions[i]; + IConfigurationElement[] configElements = currentExtension.getConfigurationElements(); + for ( int j = 0; j < configElements.length; j++ ) + { + IConfigurationElement config = configElements[j]; + if ( config.getName().equals( ICDTConstants.TAG_TEXT_HOVER ) ) + { + processTextHoverElement( textHovers, config ); + } + } + } + } + + return new CEditorTextHoverDispatcher( fEditor, textHovers ); + } + + private void processTextHoverElement( HashMap textHovers, IConfigurationElement element ) { + String perspId = element.getAttribute( ICDTConstants.ATT_PERSPECTIVE ); + ITextHover textHover = null; + try { + textHover = (ITextHover)element.createExecutableExtension( ICDTConstants.ATT_CLASS ); + } catch (CoreException e) { + } + if ( perspId != null ) { + textHovers.put( perspId, textHover ); + } + } + + /** + * @see SourceViewerConfiguration#getConfiguredContentTypes(ISourceViewer) + */ + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { IDocument.DEFAULT_CONTENT_TYPE, + CPartitionScanner.C_MULTILINE_COMMENT, + CPartitionScanner.C_SINGLE_LINE_COMMENT, + CPartitionScanner.C_STRING }; + } + + /** + * @see SourceViewerConfiguration#getContentFormatter(ISourceViewer) + */ + public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) { + String[] types= new String[] { + RuleBasedPartitioner.CONTENT_TYPES_CATEGORY + }; + + ContentFormatter formatter= new ContentFormatter(); + IFormattingStrategy strategy= new CFormattingStrategy(sourceViewer); + + formatter.setFormattingStrategy(strategy, IDocument.DEFAULT_CONTENT_TYPE); + formatter.enablePartitionAwareFormatting(false); + formatter.setPartitionManagingPositionCategories(types); + + return formatter; + } + + protected IPreferenceStore getPreferenceStore() { + return CPlugin.getDefault().getPreferenceStore(); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java new file mode 100644 index 00000000000..30087b3b23d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CTextTools.java @@ -0,0 +1,209 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.util.CColorManager; + +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.rules.RuleBasedPartitioner; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * This type shares all scanners and the color manager between + * its clients. + */ +public class CTextTools { + + private class PreferenceListener implements IPropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + adaptToPreferenceChange(event); + } + }; + + /** The color manager */ + private CColorManager fColorManager; + /** The C source code scanner */ + private CCodeScanner fCodeScanner; + /** The C++ source code scanner */ + private CppCodeScanner fCppCodeScanner; + /** The C partitions scanner */ + private CPartitionScanner fPartitionScanner; + /** The Java multiline comment scanner */ + private SingleTokenCScanner fMultilineCommentScanner; + /** The Java singleline comment scanner */ + private SingleTokenCScanner fSinglelineCommentScanner; + /** The Java string scanner */ + private SingleTokenCScanner fStringScanner; + + /** The preference store */ + private IPreferenceStore fPreferenceStore; + /** The preference change listener */ + private PreferenceListener fPreferenceListener= new PreferenceListener(); + + + /** + * Creates a new C text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public CTextTools(IPreferenceStore store) { + if(store == null) { + store = CPlugin.getDefault().getPreferenceStore(); + } + fPreferenceStore = store; + fPreferenceStore.addPropertyChangeListener(fPreferenceListener); + + fColorManager= new CColorManager(); + fCodeScanner= new CCodeScanner(fColorManager, store); + fCppCodeScanner= new CppCodeScanner(fColorManager, store); + fPartitionScanner= new CPartitionScanner(); + + fMultilineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_MULTI_LINE_COMMENT); + fSinglelineCommentScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_SINGLE_LINE_COMMENT); + fStringScanner= new SingleTokenCScanner(fColorManager, store, ICColorConstants.C_STRING); + } + + /** + * Creates a new C text tools collection and eagerly creates + * and initializes all members of this collection. + */ + public CTextTools() { + this((IPreferenceStore)null); + } + + /** + * Disposes all members of this tools collection. + */ + public void dispose() { + + fCodeScanner= null; + fPartitionScanner= null; + + + fMultilineCommentScanner= null; + fSinglelineCommentScanner= null; + fStringScanner= null; + + if (fColorManager != null) { + fColorManager.dispose(); + fColorManager= null; + } + + if (fPreferenceStore != null) { + fPreferenceStore.removePropertyChangeListener(fPreferenceListener); + fPreferenceStore= null; + fPreferenceListener= null; + } + } + + /** + * Gets the color manager. + */ + public CColorManager getColorManager() { + return fColorManager; + } + + /** + * Gets the code scanner used. + */ + public RuleBasedScanner getCCodeScanner() { + return fCodeScanner; + } + + /** + * Gets the code scanner used. + */ + public RuleBasedScanner getCppCodeScanner() { + return fCppCodeScanner; + } + + /** + * Gets the partition scanner used. + */ + public RuleBasedScanner getPartitionScanner() { + return fPartitionScanner; + } + + /** + * Gets the document provider used. + */ + public IDocumentPartitioner createDocumentPartitioner() { + + String[] types= new String[] { + CPartitionScanner.C_MULTILINE_COMMENT, + CPartitionScanner.C_SINGLE_LINE_COMMENT, + CPartitionScanner.C_STRING + }; + + return new RuleBasedPartitioner(getPartitionScanner(), types); + } + + /** + * Returns a scanner which is configured to scan Java multiline comments. + * + * @return a Java multiline comment scanner + */ + public RuleBasedScanner getMultilineCommentScanner() { + return fMultilineCommentScanner; + } + + /** + * Returns a scanner which is configured to scan Java singleline comments. + * + * @return a Java singleline comment scanner + */ + public RuleBasedScanner getSinglelineCommentScanner() { + return fSinglelineCommentScanner; + } + + /** + * Returns a scanner which is configured to scan Java strings. + * + * @return a Java string scanner + */ + public RuleBasedScanner getStringScanner() { + return fStringScanner; + } + + + /** + * Determines whether the preference change encoded by the given event + * changes the behavior of one its contained components. + * + * @param event the event to be investigated + * @return true if event causes a behavioral change + */ + public boolean affectsBehavior(PropertyChangeEvent event) { + return fCodeScanner.affectsBehavior(event) || + fCppCodeScanner.affectsBehavior(event) || + fMultilineCommentScanner.affectsBehavior(event) || + fSinglelineCommentScanner.affectsBehavior(event) || + fStringScanner.affectsBehavior(event); + } + + /** + * Adapts the behavior of the contained components to the change + * encoded in the given event. + * + * @param event the event to whch to adapt + */ + protected void adaptToPreferenceChange(PropertyChangeEvent event) { + if (fCodeScanner.affectsBehavior(event)) + fCodeScanner.adaptToPreferenceChange(event); + if (fCppCodeScanner.affectsBehavior(event)) + fCppCodeScanner.adaptToPreferenceChange(event); + if (fMultilineCommentScanner.affectsBehavior(event)) + fMultilineCommentScanner.adaptToPreferenceChange(event); + if (fSinglelineCommentScanner.affectsBehavior(event)) + fSinglelineCommentScanner.adaptToPreferenceChange(event); + if (fStringScanner.affectsBehavior(event)) + fStringScanner.adaptToPreferenceChange(event); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CWordFinder.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CWordFinder.java new file mode 100644 index 00000000000..8409c45eb0e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CWordFinder.java @@ -0,0 +1,68 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; + + +public class CWordFinder +{ + public static IRegion findWord( IDocument document, int offset ) + { + int start = -1; + int end = -1; + + try + { + int pos = offset; + char c; + + while( pos >= 0 ) + { + c = document.getChar( pos ); + if ( !Character.isJavaIdentifierPart( c ) ) + break; + --pos; + } + + start = pos; + + pos = offset; + int length = document.getLength(); + + while( pos < length ) + { + c = document.getChar( pos ); + if ( !Character.isJavaIdentifierPart( c ) ) + break; + ++pos; + } + + end = pos; + + } + catch( BadLocationException x ) + { + } + + if ( start > -1 && end > -1 ) + { + if ( start == offset && end == offset ) + return new Region( offset, 0 ); + else if ( start == offset ) + return new Region( start, end - start ); + else + return new Region( start + 1, end - start - 1 ); + } + + return null; + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ContentAssistPreference.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ContentAssistPreference.java new file mode 100644 index 00000000000..a73cc2e3507 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/ContentAssistPreference.java @@ -0,0 +1,188 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.util.PropertyChangeEvent; + + + +public class ContentAssistPreference { + + /** Preference key for content assist auto activation */ + public final static String AUTOACTIVATION= "content_assist_autoactivation"; + /** Preference key for content assist auto activation delay */ + public final static String AUTOACTIVATION_DELAY= "content_assist_autoactivation_delay"; + /** Preference key for content assist proposal color */ + public final static String PROPOSALS_FOREGROUND= "content_assist_proposals_foreground"; + /** Preference key for content assist proposal color */ + public final static String PROPOSALS_BACKGROUND= "content_assist_proposals_background"; + /** Preference key for content assist parameters color */ + public final static String PARAMETERS_FOREGROUND= "content_assist_parameters_foreground"; + /** Preference key for content assist parameters color */ + public final static String PARAMETERS_BACKGROUND= "content_assist_parameters_background"; + /** Preference key for content assist auto insert */ + public final static String AUTOINSERT= "content_assist_autoinsert"; + + /** Preference key for java content assist auto activation triggers */ + public final static String AUTOACTIVATION_TRIGGERS_C= "content_assist_autoactivation_triggers_java"; + + /** Preference key for visibility of proposals */ + public final static String SHOW_DOCUMENTED_PROPOSALS= "content_assist_show_visible_proposals"; + /** Preference key for alphabetic ordering of proposals */ + public final static String ORDER_PROPOSALS= "content_assist_order_proposals"; + /** Preference key for case sensitivity of propsals */ + public final static String CASE_SENSITIVITY= "content_assist_case_sensitivity"; + /** Preference key for adding imports on code assist */ + public final static String ADD_INCLUDE= "content_assist_add_import"; + + private static Color getColor(IPreferenceStore store, String key, IColorManager manager) { + RGB rgb= PreferenceConverter.getColor(store, key); + return manager.getColor(rgb); + } + + private static Color getColor(IPreferenceStore store, String key) { + CTextTools textTools= CPlugin.getDefault().getTextTools(); + return getColor(store, key, textTools.getColorManager()); + } + + private static CCompletionProcessor getCProcessor(ContentAssistant assistant) { + IContentAssistProcessor p= assistant.getContentAssistProcessor(IDocument.DEFAULT_CONTENT_TYPE); + if (p instanceof CCompletionProcessor) + return (CCompletionProcessor) p; + return null; + } + + private static void configureCProcessor(ContentAssistant assistant, IPreferenceStore store) { + CCompletionProcessor jcp= getCProcessor(assistant); + if (jcp == null) + return; + + String triggers= store.getString(AUTOACTIVATION_TRIGGERS_C); + if (triggers != null) + jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray()); + + boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS); + //jcp.restrictProposalsToVisibility(enabled); + + enabled= store.getBoolean(CASE_SENSITIVITY); + jcp.restrictProposalsToMatchingCases(enabled); + + enabled= store.getBoolean(ORDER_PROPOSALS); + jcp.orderProposalsAlphabetically(enabled); + + enabled= store.getBoolean(ADD_INCLUDE); + jcp.allowAddingIncludes(enabled); + } + + + /** + * Configure the given content assistant from the given store. + */ + public static void configure(ContentAssistant assistant, IPreferenceStore store) { + + CTextTools textTools= CPlugin.getDefault().getTextTools(); + IColorManager manager= textTools.getColorManager(); + + + boolean enabled= store.getBoolean(AUTOACTIVATION); + assistant.enableAutoActivation(enabled); + + int delay= store.getInt(AUTOACTIVATION_DELAY); + assistant.setAutoActivationDelay(delay); + + //Color c= getColor(store, PROPOSALS_FOREGROUND, manager); + //assistant.setProposalSelectorForeground(c); + + Color c= getColor(store, PROPOSALS_BACKGROUND, manager); + assistant.setContextInformationPopupBackground(c); + + c= getColor(store, PARAMETERS_FOREGROUND, manager); + //assistant.setContextInformationPopupForeground(c); + //assistant.setContextSelectorForeground(c); + + c= getColor(store, PARAMETERS_BACKGROUND, manager); + assistant.setContextInformationPopupBackground(c); + //assistant.setContextSelectorBackground(c); + + enabled= store.getBoolean(AUTOINSERT); + //assistant.enableAutoInsert(enabled); + + configureCProcessor(assistant, store); + } + + + private static void changeCProcessor(ContentAssistant assistant, IPreferenceStore store, String key) { + CCompletionProcessor jcp= getCProcessor(assistant); + if (jcp == null) + return; + + if (AUTOACTIVATION_TRIGGERS_C.equals(key)) { + String triggers= store.getString(AUTOACTIVATION_TRIGGERS_C); + if (triggers != null) + jcp.setCompletionProposalAutoActivationCharacters(triggers.toCharArray()); + } else if (SHOW_DOCUMENTED_PROPOSALS.equals(key)) { + //boolean enabled= store.getBoolean(SHOW_DOCUMENTED_PROPOSALS); + //jcp.restrictProposalsToVisibility(enabled); + } else if (CASE_SENSITIVITY.equals(key)) { + boolean enabled= store.getBoolean(CASE_SENSITIVITY); + jcp.restrictProposalsToMatchingCases(enabled); + } else if (ORDER_PROPOSALS.equals(key)) { + boolean enable= store.getBoolean(ORDER_PROPOSALS); + jcp.orderProposalsAlphabetically(enable); + } else if (ADD_INCLUDE.equals(key)) { + boolean enabled= store.getBoolean(ADD_INCLUDE); + jcp.allowAddingIncludes(enabled); + } + } + + /** + * Changes the configuration of the given content assistant according to the given property + * change event and the given preference store. + */ + public static void changeConfiguration(ContentAssistant assistant, IPreferenceStore store, PropertyChangeEvent event) { + + String p= event.getProperty(); + + if (AUTOACTIVATION.equals(p)) { + boolean enabled= store.getBoolean(AUTOACTIVATION); + assistant.enableAutoActivation(enabled); + } else if (AUTOACTIVATION_DELAY.equals(p)) { + int delay= store.getInt(AUTOACTIVATION_DELAY); + assistant.setAutoActivationDelay(delay); + } else if (PROPOSALS_FOREGROUND.equals(p)) { + //Color c= getColor(store, PROPOSALS_FOREGROUND); + //assistant.setProposalSelectorForeground(c); + } else if (PROPOSALS_BACKGROUND.equals(p)) { + //Color c= getColor(store, PROPOSALS_BACKGROUND); + //assistant.setProposalSelectorBackground(c); + } else if (PARAMETERS_FOREGROUND.equals(p)) { + //Color c= getColor(store, PARAMETERS_FOREGROUND); + //assistant.setContextInformationPopupForeground(c); + //assistant.setContextSelectorForeground(c); + } else if (PARAMETERS_BACKGROUND.equals(p)) { + Color c= getColor(store, PARAMETERS_BACKGROUND); + assistant.setContextInformationPopupBackground(c); + //assistant.setContextSelectorBackground(c); + } else if (AUTOINSERT.equals(p)) { + //boolean enabled= store.getBoolean(AUTOINSERT); + //assistant.enableAutoInsert(enabled); + } + + changeCProcessor(assistant, store, p); + } +} + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java new file mode 100644 index 00000000000..f288672293c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CppCodeScanner.java @@ -0,0 +1,261 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import org.eclipse.cdt.internal.ui.text.util.CWordDetector; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import java.util.Map; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.PatternRule; +import org.eclipse.jface.text.rules.SingleLineRule; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * A C code scanner. + */ +public final class CppCodeScanner extends AbstractCScanner { + + private class CWordRule implements IRule { + + protected static final int UNDEFINED= -1; + + /** The word detector used by this rule */ + protected IWordDetector fDetector; + /** The default token to be returned on success and if nothing else has been specified. */ + protected IToken fDefaultToken; + /** The column constraint */ + protected int fColumn= UNDEFINED; + /** The table of predefined words and token for this rule */ + protected Map fWords= new HashMap(); + + private StringBuffer fBuffer= new StringBuffer(); + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the scanner + * will be rolled back and an undefined token will be returned in order to allow + * any subsequent rules to analyze the characters. + * + * @param detector the word detector to be used by this rule, may not be null + * + * @see #addWord + */ + public CWordRule(IWordDetector detector) { + this(detector, Token.UNDEFINED); + } + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the + * specified default token will be returned. + * + * @param detector the word detector to be used by this rule, may not be null + * @param defaultToken the default token to be returned on success + * if nothing else is specified, may not be null + * + * @see #addWord + */ + public CWordRule(IWordDetector detector, IToken defaultToken) { + + Assert.isNotNull(detector); + Assert.isNotNull(defaultToken); + + fDetector= detector; + fDefaultToken= defaultToken; + } + /** + * Adds a word and the token to be returned if it is detected. + * + * @param word the word this rule will search for, may not be null + * @param token the token to be returned if the word has been found, may not be null + */ + public void addWord(String word, IToken token) { + Assert.isNotNull(word); + Assert.isNotNull(token); + + fWords.put(word, token); + } + /* + * @see IRule#evaluate + */ + public IToken evaluate(ICharacterScanner scanner) { + + int c= scanner.read(); + if (Character.isJavaIdentifierStart((char) c) || (c == '#' && scanner.getColumn() == 1)) { + fBuffer.setLength(0); + do { + fBuffer.append((char) c); + c= scanner.read(); + } while (Character.isJavaIdentifierPart((char) c)); + scanner.unread(); + + IToken token= (IToken) fWords.get(fBuffer.toString()); + if (token != null) + return token; + + //if (fDefaultToken.isUndefined()) + // unreadBuffer(scanner); + + return fDefaultToken; + } + + scanner.unread(); + return Token.UNDEFINED; + } + /** + * Sets a column constraint for this rule. If set, the rule's token + * will only be returned if the pattern is detected starting at the + * specified column. If the column is smaller then 0, the column + * constraint is considered removed. + * + * @param column the column in which the pattern starts + */ + public void setColumnConstraint(int column) { + if (column < 0) + column= UNDEFINED; + fColumn= column; + } + /** + * Returns the characters in the buffer to the scanner. + * + * @param scanner the scanner to be used + */ + protected void unreadBuffer(ICharacterScanner scanner) { + for (int i= fBuffer.length() - 1; i >= 0; i--) + scanner.unread(); + } + }; + + private static String[] fgKeywords= { + "and", "and_eq", "asm", "auto", + "bitand", "bitor", "break", + "case", "catch", "class", "compl", "const", "const_cast", "continue", + "default", "delete", "do", "dynamic_cast", + "else", "enum", "explicit", "export", "extern", + "false", "final", "finally", "for", "friend", + "goto", + "if", "inline", + "mutable", + "namespace", "new", "not", "not_eq", + "operator", "or", "or_eq", + "private", "protected", "public", + "redeclared", "register", "reinterpret_cast", "return", "restrict", + "sizeof", "static", "static_cast", "struct", "switch", + "template", "this", "throw", "true", "try", "typedef", "typeid", "typename", + "union", "using", + "virtual", "volatile", + "while", + "xor", "xor_eq" + + }; + + + private static String[] fgTypes= { "bool", "char", "double", "float", "int", "long", "short", "signed", "unsigned", "void", "wchar_t", "_Bool", "_Complex", "_Imaginary"}; + private static String[] fgConstants= { "false", "NULL", "true", "__DATE__", "__LINE__", "__TIME__", "__FILE__", "__STDC__"}; + private static String[] fgPreprocessor= { "#define", "#include", "#error", "#pragma", "#ifdef", "#ifndef", "#line", "#undef", "#if", "#else", "#elif", "#endif"}; + + + private static String[] fgTokenProperties= { + ICColorConstants.C_KEYWORD, + ICColorConstants.C_TYPE, + ICColorConstants.C_STRING, + ICColorConstants.C_DEFAULT + }; + + + /** + * Creates a C++ code scanner + */ + public CppCodeScanner(IColorManager manager, IPreferenceStore store) { + super(manager, store); + initialize(); + } + + /* + * @see AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fgTokenProperties; + } + + /* + * @see AbstractCScanner#createRules() + */ + protected List createRules() { + + List rules= new ArrayList(); + + // Add rule for strings + Token token= getToken(ICColorConstants.C_STRING); + // Add rule for strings and character constants. + rules.add(new SingleLineRule("'", "'", token, '\\')); + + + + // Add generic whitespace rule. + //rules.add(new WhitespaceRule(new CWhitespaceDetector())); + + + // Add word rule for keywords, types, and constants. + token= getToken(ICColorConstants.C_DEFAULT); + CWordRule wordRule= new CWordRule(new CWordDetector(), token); + + token= getToken(ICColorConstants.C_KEYWORD); + for (int i=0; iRGB objects. Until the dispose + * method is called, the same color object is returned for + * equal keys and equal RGB values. + *

+ * This interface may be implemented by clients. + *

+ * + * @see IJavaColorConstants + */ +public interface IColorManager { + + /** + * Returns a color object for the given key. The color objects + * are remembered internally; the same color object is returned + * for equal keys. + * + * @param key the color key + * @return the color object for the given key + */ + Color getColor(String key); + + /** + * Returns the color object for the value represented by the given + * RGB object. + * + * @param rgb the rgb color specification + * @return the color object for the given rgb value + */ + Color getColor(RGB rgb); + + /** + * Disposes all color objects remembered by this color manager. + */ + void dispose(); +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/IColorManagerExtension.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/IColorManagerExtension.java new file mode 100644 index 00000000000..2f81ca0286c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/IColorManagerExtension.java @@ -0,0 +1,34 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.RGB; + + +/** + * For internal use only. Not API.

+ * A color manager extension is for extending + * IColorManager instances with new functionality. + */ +public interface IColorManagerExtension { + + /** + * Remembers the given color specification under the given key. + * + * @param key the color key + * @param rgb the color specification + * @exception UnsupportedOperationException if there is already a + * color specification remembered under the given key + */ + void bindColor(String key, RGB rgb); + + + /** + * Forgets the color specification remembered under the given key. + * @param key the color key + */ + void unbindColor(String key); +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/LineBreakingReader.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/LineBreakingReader.java new file mode 100644 index 00000000000..2844da78b62 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/LineBreakingReader.java @@ -0,0 +1,101 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; + +import java.text.BreakIterator; +import org.eclipse.swt.graphics.GC; + +/* + * Not a real reader. Could change if requested + */ +public class LineBreakingReader { + + private BufferedReader fReader; + private GC fGC; + private int fMaxWidth; + + private String fLine; + private int fOffset; + + private BreakIterator fLineBreakIterator; + private int findNextBreakOffset(int currOffset) { + int currWidth= 0; + int nextOffset= fLineBreakIterator.following(currOffset); + while (nextOffset != BreakIterator.DONE) { + String word= fLine.substring(currOffset, nextOffset); + int wordWidth= fGC.textExtent(word).x; + int nextWidth= wordWidth + currWidth; + if (nextWidth > fMaxWidth) { + if (currWidth > 0) { + return currOffset; + } else { + return nextOffset; + } + } + currWidth= nextWidth; + currOffset= nextOffset; + nextOffset= fLineBreakIterator.next(); + } + return nextOffset; + } + private int findWordBegin(int idx) { + while (idx < fLine.length() && Character.isWhitespace(fLine.charAt(idx))) { + idx++; + } + return idx; + } + /** + * Creates a reader that breaks an input text to fit in a given width. + * @param reader Reader of the input text + * @param gc The graphic context that defines the currently used font sizes + * @param maxLineWidth The max width (pixes) where the text has to fit in + */ + public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) { + fReader= new BufferedReader(reader); + fGC= gc; + fMaxWidth= maxLineWidth; + fOffset= 0; + fLine= null; + fLineBreakIterator= BreakIterator.getLineInstance(); + } + /** + * Reads the next line. The lengths of the line will not exceed the gived maximum + * width. + */ + public String readLine() throws IOException { + if (fLine == null) { + String line= fReader.readLine(); + if (line == null) { + return null; + } + + int lineLen= fGC.textExtent(line).x; + if (lineLen < fMaxWidth) { + return line; + } + fLine= line; + fLineBreakIterator.setText(line); + fOffset= 0; + } + int breakOffset= findNextBreakOffset(fOffset); + String res; + if (breakOffset != BreakIterator.DONE) { + res= fLine.substring(fOffset, breakOffset); + fOffset= findWordBegin(breakOffset); + if (fOffset == fLine.length()) { + fLine= null; + } + } else { + res= fLine.substring(fOffset); + fLine= null; + } + return res; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleCharReader.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleCharReader.java new file mode 100644 index 00000000000..4979ce16232 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleCharReader.java @@ -0,0 +1,57 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.io.Reader; + + +public abstract class SingleCharReader extends Reader { + + /** + * @see Reader#read(char) + */ + public abstract int read() throws IOException; + + + /** + * @see Reader#read(char[],int,int) + */ + public int read(char cbuf[], int off, int len) throws IOException { + int end= off + len; + for (int i= off; i < end; i++) { + int ch= read(); + if (ch == -1) { + if (i == off) { + return -1; + } else { + return i - off; + } + } + cbuf[i]= (char)ch; + } + return len; + } + + /** + * @see Reader#ready() + */ + public boolean ready() throws IOException { + return true; + } + + /** + * Gets the content as a String + */ + public String getString() throws IOException { + StringBuffer buf= new StringBuffer(); + int ch; + while ((ch= read()) != -1) { + buf.append((char)ch); + } + return buf.toString(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleTokenCScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleTokenCScanner.java new file mode 100644 index 00000000000..2eb92e70b0a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/SingleTokenCScanner.java @@ -0,0 +1,106 @@ +package org.eclipse.cdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.text.eclipse2.Token; +import java.util.List; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.IToken; + + +/** + * + */ +public final class SingleTokenCScanner extends AbstractCScanner{ + + protected IToken fDefaultReturnToken; + private String[] fProperty; + + public SingleTokenCScanner(IColorManager manager, IPreferenceStore store, String property) { + super(manager, store, 20); + fProperty= new String[] { property }; + initialize(); + } + + /* + * @see AbstractCScanner#getTokenProperties() + */ + protected String[] getTokenProperties() { + return fProperty; + } + + /* + * @see AbstractCScanner#createRules() + */ + protected List createRules() { + fDefaultReturnToken= getToken(fProperty[0]); + setDefaultReturnToken(fDefaultReturnToken); + return null; + } + + /** + * setRange -- sets the range to be scanned + */ + + private int position, end; + private int size; + public void setRange(IDocument document, int offset, int length) { + + super.setRange(document, offset, length); + position = offset; + size = length; + end = offset + length; + } + /** + * Returns the next token in the document. + * + * @return the next token in the document + */ + public IToken nextToken() { + + fTokenOffset = position; + + if(position < end) { + size = end - position; + position = end; + return fDefaultReturnToken; + } else { + return Token.EOF; + } + } + + public int getTokenLength() { + return size; + } + + //public int getTokenOffset() { + // return position; + //} + /* while (true) { + + fTokenOffset= fOffset; + fColumn= UNDEFINED; + + if (fRules != null) { + for (int i= 0; i < fRules.length; i++) { + token= (fRules[i].evaluate(this)); + if (!token.isUndefined()) + return token; + } + } + + if (read() == EOF) + return Token.EOF; + else + return fDefaultReturnToken; + } + } */ + +} + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CAbstractDocument.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CAbstractDocument.java new file mode 100644 index 00000000000..23891b415f1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CAbstractDocument.java @@ -0,0 +1,1119 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.IDocumentPartitioningListener; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextStore; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TypedRegion; +import org.eclipse.jface.util.Assert; + + +/** + * Abstract implementation of IDocument. + * Implements the complete contract of IDocument. + * An AbstractDocument supports the following implementation plug-ins: + *

    + *
  • a text store for storing and managing the document's content + *
  • a line tracker to map character positions to line numbers and vice versa + *
+ * This class must be subclassed. Subclasses must configure which implementation + * plug-ins the document should use. Subclasses are not intended to overwrite + * existing methods. + * + * @see IDocument + * @see ITextStore + * @see ILineTracker + */ +public abstract class CAbstractDocument implements IDocument, IDocumentExtension { + + /** The document's text store */ + private ITextStore fStore; + /** The document's line tracker */ + private ILineTracker fTracker; + /** The document's partitioner */ + private IDocumentPartitioner fDocumentPartitioner; + /** The document's partitioner casted to IDocumentPartitionerExtension. */ + private IDocumentPartitionerExtension fDocumentPartitionerExtension; + /** The registered document listeners */ + private List fDocumentListeners; + /** The registered prenotified document listeners */ + private List fPrenotifiedDocumentListeners; + /** The registered document partitioning listeners */ + private List fDocumentPartitioningListeners; + /** All positions managed by the document */ + private Map fPositions; + /** All registered document position updaters */ + private List fPositionUpdaters; + + /** The list of post notification changes */ + private List fPostNotificationChanges; + /** The reentrance count for post notification changes. */ + private int fReentranceCount= 0; + /** Indicates whether post notification change processing has been stopped. */ + private int fStoppedCount= 0; + + /** + * The default constructor does not perform any configuration + * but leaves it to the clients who must first initialize the + * implementation plug-ins and then call completeInitialization. + * Results in the construction of an empty document. + */ + protected CAbstractDocument() { + } + + + //--- accessor to fields ------------------------------- + + /** + * Returns the document's text store. Assumes that the + * document has been initialized with a text store. + * + * @return the document's text store + */ + protected ITextStore getStore() { + Assert.isNotNull(fStore); + return fStore; + } + + /** + * Returns the document's line tracker. Assumes that the + * document has been initialized with a line tracker. + * + * @return the document's line tracker + */ + protected ILineTracker getTracker() { + Assert.isNotNull(fTracker); + return fTracker; + } + + /** + * Returns the document's document listeners. + * + * @return the document's document listeners + */ + protected List getDocumentListeners() { + return fDocumentListeners; + } + + /** + * Returns the document's partitioning listeners . + * + * @return the document's partitioning listeners + */ + protected List getDocumentPartitioningListeners() { + return fDocumentPartitioningListeners; + } + + /** + * Returns all positions managed by the document grouped by category. + * + * @return the document's positions + */ + protected Map getDocumentManagedPositions() { + return fPositions; + } + + /* + * @see IDocument#getDocumentPartitioner + */ + public IDocumentPartitioner getDocumentPartitioner() { + return fDocumentPartitioner; + } + + + + //--- implementation configuration interface ------------ + + /** + * Sets the document's text store. + * Must be called inside the constructor. + * + * @param store the document's text store + */ + protected void setTextStore(ITextStore store) { + fStore= store; + } + + /** + * Sets the document's line tracker. + * Must be called inside the constructor. + * + * @param tracker the document's line tracker + */ + protected void setLineTracker(ILineTracker tracker) { + fTracker= tracker; + } + + /* + * @see IDocument#setDocumentPartitioner + */ + public void setDocumentPartitioner(IDocumentPartitioner partitioner) { + fDocumentPartitioner= partitioner; + if (fDocumentPartitioner instanceof IDocumentPartitionerExtension) + fDocumentPartitionerExtension= (IDocumentPartitionerExtension) fDocumentPartitioner; + + fireDocumentPartitioningChanged(new Region(0, getLength())); + } + + /** + * Initializes document listeners, positions, and position updaters. + * Must be called inside the constructor after the implementation plug-ins + * have been set. + */ + protected void completeInitialization() { + + fPositions= new HashMap(); + fPositionUpdaters= new ArrayList(); + fDocumentListeners= new ArrayList(); + fPrenotifiedDocumentListeners= new ArrayList(); + fDocumentPartitioningListeners= new ArrayList(); + + addPositionCategory(DEFAULT_CATEGORY); + addPositionUpdater(new DefaultPositionUpdater(DEFAULT_CATEGORY)); + } + + + //------------------------------------------------------- + + /* + * @see IDocument#addDocumentListener + */ + public void addDocumentListener(IDocumentListener listener) { + Assert.isNotNull(listener); + if (! fDocumentListeners.contains(listener)) + fDocumentListeners.add(listener); + } + + /* + * @see IDocument#removeDocumentListener + */ + public void removeDocumentListener(IDocumentListener listener) { + Assert.isNotNull(listener); + fDocumentListeners.remove(listener); + } + + /* + * @see IDocument#addPrenotifiedDocumentListener(IDocumentListener) + */ + public void addPrenotifiedDocumentListener(IDocumentListener listener) { + Assert.isNotNull(listener); + if (! fPrenotifiedDocumentListeners.contains(listener)) + fPrenotifiedDocumentListeners.add(listener); + } + + /* + * @see IDocument#removePrenotifiedDocumentListener(IDocumentListener) + */ + public void removePrenotifiedDocumentListener(IDocumentListener listener) { + Assert.isNotNull(listener); + fPrenotifiedDocumentListeners.remove(listener); + } + + /* + * @see IDocument#addDocumentPartitioningListener + */ + public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) { + Assert.isNotNull(listener); + if (! fDocumentPartitioningListeners.contains(listener)) + fDocumentPartitioningListeners.add(listener); + } + + /* + * @see IDocument#removeDocumentPartitioningListener + */ + public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) { + Assert.isNotNull(listener); + fDocumentPartitioningListeners.remove(listener); + } + + /* + * @see IDocument#addPosition + */ + public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException { + + if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getLength())) + throw new BadLocationException(); + + if (category == null) + throw new BadPositionCategoryException(); + + List list= (List) fPositions.get(category); + if (list == null) + throw new BadPositionCategoryException(); + + list.add(computeIndexInPositionList(list, position.offset), position); + } + + /* + * @see IDocument#addPosition + */ + public void addPosition(Position position) throws BadLocationException { + try { + addPosition(DEFAULT_CATEGORY, position); + } catch (BadPositionCategoryException e) { + } + } + + /* + * @see IDocument#addPositionCategory + */ + public void addPositionCategory(String category) { + + if (category == null) + return; + + if (!containsPositionCategory(category)) + fPositions.put(category, new ArrayList()); + } + + /* + * @see IDocument#addPositionUpdater + */ + public void addPositionUpdater(IPositionUpdater updater) { + insertPositionUpdater(updater, fPositionUpdaters.size()); + } + + /* + * @see IDocument#containsPosition + */ + public boolean containsPosition(String category, int offset, int length) { + + if (category == null) + return false; + + List list= (List) fPositions.get(category); + if (list == null) + return false; + + int size= list.size(); + if (size == 0) + return false; + + int index= computeIndexInPositionList(list, offset); + if (index < size) { + Position p= (Position) list.get(index); + while (p != null && p.offset == offset) { + if (p.length == length) + return true; + ++ index; + p= (index < size) ? (Position) list.get(index) : null; + } + } + + return false; + } + + /* + * @see IDocument#containsPositionCategory + */ + public boolean containsPositionCategory(String category) { + if (category != null) + return fPositions.containsKey(category); + return false; + } + + + /** + * Computes the index in the list of positions at which a position with the given + * offset would be inserted. The position is supposed to become the first in this list + * of all positions with the same offset. + * + * @param positions the list in which the index is computed + * @param offset the offset for which the index is computed + * @return the computed index + * + * @see IDocument#computeIndexInCategory(String, int) + */ + protected int computeIndexInPositionList(List positions, int offset) { + + if (positions.size() == 0) + return 0; + + int left= 0; + int right= positions.size() -1; + int mid= 0; + Position p= null; + + while (left < right) { + + mid= (left + right) / 2; + + p= (Position) positions.get(mid); + if (offset < p.getOffset()) { + if (left == mid) + right= left; + else + right= mid -1; + } else if (offset > p.getOffset()) { + if (right == mid) + left= right; + else + left= mid +1; + } else if (offset == p.getOffset()) { + left= right= mid; + } + + } + + int pos= left; + p= (Position) positions.get(pos); + if (offset > p.getOffset()) { + // append to the end + pos++; + } else { + // entry will became the first of all entries with the same offset + do { + --pos; + if (pos < 0) + break; + p= (Position) positions.get(pos); + } while (offset == p.getOffset()); + ++pos; + } + + Assert.isTrue(0 <= pos && pos <= positions.size()); + + return pos; + } + + + /* + * @see IDocument#computeIndexInCategory + */ + public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException { + + if (0 > offset || offset > getLength()) + throw new BadLocationException(); + + List c= (List) fPositions.get(category); + if (c == null) + throw new BadPositionCategoryException(); + + return computeIndexInPositionList(c, offset); + } + + /** + * Fires the document partitioning changed notification to all registered + * document partitioning listeners. Uses a robust iterator. + * @deprecated use fireDocumentPartitioningChanged(IRegion) instead + */ + protected void fireDocumentPartitioningChanged() { + + if (fDocumentPartitioningListeners != null && fDocumentPartitioningListeners.size() > 0) { + + List list= new ArrayList(fDocumentPartitioningListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentPartitioningListener l= (IDocumentPartitioningListener) e.next(); + l.documentPartitioningChanged(this); + } + } + } + + /** + * Fires the document partitioning changed notification to all registered + * document partitioning listeners. Uses a robust iterator. + * + * @param region the region in which partitioning has changed + */ + protected void fireDocumentPartitioningChanged(IRegion region) { + + if (fDocumentPartitioningListeners != null && fDocumentPartitioningListeners.size() > 0) { + + List list= new ArrayList(fDocumentPartitioningListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentPartitioningListener l= (IDocumentPartitioningListener) e.next(); + if (l instanceof IDocumentPartitioningListenerExtension) + ((IDocumentPartitioningListenerExtension) l).documentPartitioningChanged(this, region); + else + l.documentPartitioningChanged(this); + } + } + } + + /** + * Fires the given document event to all registers document listeners informing them + * about the forthcoming document manipulation. Uses a robust iterator. + * + * @param event the event to be sent out + */ + protected void fireDocumentAboutToBeChanged(DocumentEvent event) { + + // IDocumentExtension + if (fReentranceCount == 0) + flushPostNotificationChanges(); + + if (fDocumentPartitioner != null) + fDocumentPartitioner.documentAboutToBeChanged(event); + + if (fPrenotifiedDocumentListeners.size() > 0) { + + List list= new ArrayList(fPrenotifiedDocumentListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentListener l= (IDocumentListener) e.next(); + l.documentAboutToBeChanged(event); + } + } + + if (fDocumentListeners.size() > 0) { + + List list= new ArrayList(fDocumentListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentListener l= (IDocumentListener) e.next(); + l.documentAboutToBeChanged(event); + } + } + } + + /** + * Updates document partitioning and document positions according to the + * specification given by the document event. + * + * @param event the document event describing the change to which structures must be adapted + */ + protected void updateDocumentStructures(DocumentEvent event) { + boolean partitioningChanged= false; + IRegion changedRegion= null; + + if (fDocumentPartitioner != null) { + if (fDocumentPartitionerExtension != null) { + changedRegion= fDocumentPartitionerExtension.documentChanged2(event); + partitioningChanged= (changedRegion != null); + } else + partitioningChanged= fDocumentPartitioner.documentChanged(event); + } + + if (fPositions.size() > 0) + updatePositions(event); + + if (partitioningChanged) + fireDocumentPartitioningChanged(changedRegion); + } + + /** + * Updates the internal document structures and informs all document listeners. + * Uses a robust iterator. + * + * @param event the document event to be sent out + */ + protected void fireDocumentChanged(DocumentEvent event) { + updateDocumentStructures(event); + + if (fPrenotifiedDocumentListeners.size() > 0) { + + List list= new ArrayList(fPrenotifiedDocumentListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentListener l= (IDocumentListener) e.next(); + l.documentChanged(event); + } + } + + if (fDocumentListeners.size() > 0) { + + List list= new ArrayList(fDocumentListeners); + Iterator e= list.iterator(); + while (e.hasNext()) { + IDocumentListener l= (IDocumentListener) e.next(); + l.documentChanged(event); + } + } + + // IDocumentExtension + ++ fReentranceCount; + try { + if (fReentranceCount == 1) + executePostNotificationChanges(); + } finally { + -- fReentranceCount; + } + } + + /* + * @see IDocument#getChar + */ + public char getChar(int pos) throws BadLocationException { + if ((0 > pos) || (pos >= getLength())) + throw new BadLocationException(); + return getStore().get(pos); + } + + /* + * @see IDocument#getContentType + */ + public String getContentType(int offset) throws BadLocationException { + if ((0 > offset) || (offset > getLength())) + throw new BadLocationException(); + + if (fDocumentPartitioner == null) + return DEFAULT_CONTENT_TYPE; + + return fDocumentPartitioner.getContentType(offset); + } + + /* + * @see IDocument#getLegalContentTypes + */ + public String[] getLegalContentTypes() { + if (fDocumentPartitioner == null) + return new String[] { DEFAULT_CONTENT_TYPE }; + return fDocumentPartitioner.getLegalContentTypes(); + } + + /* + * @see IDocument#getLength + */ + public int getLength() { + return getStore().getLength(); + } + + /* + * @see IDocument#getLineDelimiter + */ + public String getLineDelimiter(int line) throws BadLocationException { + return getTracker().getLineDelimiter(line); + } + + /* + * @see IDocument#getLegalLineDelimiters + */ + public String[] getLegalLineDelimiters() { + return getTracker().getLegalLineDelimiters(); + } + + /* + * @see IDocument#getLineLength + */ + public int getLineLength(int line) throws BadLocationException { + return getTracker().getLineLength(line); + } + + /* + * @see IDocument#getLineOfOffset + */ + public int getLineOfOffset(int pos) throws BadLocationException { + return getTracker().getLineNumberOfOffset(pos); + } + + /* + * @see IDocument#getLineOffset + */ + public int getLineOffset(int line) throws BadLocationException { + return getTracker().getLineOffset(line); + } + + /* + * @see IDocument#getLineInformation + */ + public IRegion getLineInformation(int line) throws BadLocationException { + return getTracker().getLineInformation(line); + } + + /* + * @see IDocument#getLineInformationOfOffset + */ + public IRegion getLineInformationOfOffset(int offset) throws BadLocationException { + return getTracker().getLineInformationOfOffset(offset); + } + + /* + * @see IDocument#getNumberOfLines + */ + public int getNumberOfLines() { + return getTracker().getNumberOfLines(); + } + + /* + * @see IDocument#getNumberOfLines(int, int) + */ + public int getNumberOfLines(int offset, int length) throws BadLocationException { + return getTracker().getNumberOfLines(offset, length); + } + + /* + * @see IDocument#computeNumberOfLines(String) + */ + public int computeNumberOfLines(String text) { + return getTracker().computeNumberOfLines(text); + } + + /* + * @see IDocument#getPartition + */ + public ITypedRegion getPartition(int offset) throws BadLocationException { + if ((0 > offset) || (offset > getLength())) + throw new BadLocationException(); + + if (fDocumentPartitioner == null) + return new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE); + + return fDocumentPartitioner.getPartition(offset); + } + + /* + * @see IDocument#computePartitioning + */ + public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException { + if ((0 > offset) || (0 > length) || (offset + length > getLength())) + throw new BadLocationException(); + + if (fDocumentPartitioner == null) + return new TypedRegion[] { new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE) }; + + return fDocumentPartitioner.computePartitioning(offset, length); + } + + /* + * @see IDocument#getPositions + */ + public Position[] getPositions(String category) throws BadPositionCategoryException { + + if (category == null) + throw new BadPositionCategoryException(); + + List c= (List) fPositions.get(category); + if (c == null) + throw new BadPositionCategoryException(); + + Position[] positions= new Position[c.size()]; + c.toArray(positions); + return positions; + } + + /* + * @see IDocument#getPositionCategories + */ + public String[] getPositionCategories() { + String[] categories= new String[fPositions.size()]; + Iterator keys= fPositions.keySet().iterator(); + for (int i= 0; i < categories.length; i++) + categories[i]= (String) keys.next(); + return categories; + } + + /* + * @see IDocument#getPositionUpdaters + */ + public IPositionUpdater[] getPositionUpdaters() { + IPositionUpdater[] updaters= new IPositionUpdater[fPositionUpdaters.size()]; + fPositionUpdaters.toArray(updaters); + return updaters; + } + + /* + * @see IDocument#get + */ + public String get() { + return getStore().get(0, getLength()); + } + + /* + * @see IDocument#get + */ + public String get(int pos, int length) throws BadLocationException { + int myLength= getLength(); + if ((0 > pos) || (0 > length) || (pos + length > myLength)) + throw new BadLocationException(); + return getStore().get(pos, length); + } + + /* + * @see IDocument#insertPositionUpdater + */ + public void insertPositionUpdater(IPositionUpdater updater, int index) { + + for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) { + if (fPositionUpdaters.get(i) == updater) + return; + } + + if (index == fPositionUpdaters.size()) + fPositionUpdaters.add(updater); + else + fPositionUpdaters.add(index, updater); + } + + /* + * @see IDocument#removePosition + */ + public void removePosition(String category, Position position) throws BadPositionCategoryException { + + if (position == null) + return; + + if (category == null) + throw new BadPositionCategoryException(); + + List c= (List) fPositions.get(category); + if (c == null) + throw new BadPositionCategoryException(); + + c.remove(position); + } + + /* + * @see IDocument#removePosition + */ + public void removePosition(Position position) { + try { + removePosition(DEFAULT_CATEGORY, position); + } catch (BadPositionCategoryException e) { + } + } + + /* + * @see IDocument#removePositionCategory + */ + public void removePositionCategory(String category) throws BadPositionCategoryException { + + if (category == null) + return; + + if ( !containsPositionCategory(category)) + throw new BadPositionCategoryException(); + + fPositions.remove(category); + } + + /* + * @see IDocument#removePositionUpdater + */ + public void removePositionUpdater(IPositionUpdater updater) { + for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) { + if (fPositionUpdaters.get(i) == updater) { + fPositionUpdaters.remove(i); + return; + } + } + } + + /* + * @see IDocument#replace + */ + public void replace(int pos, int length, String text) throws BadLocationException { + if ((0 > pos) || (0 > length) || (pos + length > getLength())) + throw new BadLocationException(); + + DocumentEvent e= new DocumentEvent(this, pos, length, text); + fireDocumentAboutToBeChanged(e); + + getStore().replace(pos, length, text); + getTracker().replace(pos, length, text); + + fireDocumentChanged(e); + } + + /* + * @see IDocument#set + */ + public void set(String text) { + int length= getStore().getLength(); + DocumentEvent e= new DocumentEvent(this, 0, length, text); + fireDocumentAboutToBeChanged(e); + + getStore().set(text); + getTracker().set(text); + + fireDocumentChanged(e); + } + + /** + * Updates all positions of all categories to the change + * described by the document event. All registered document + * updaters are called in the sequence they have been arranged. + * Uses a robust iterator. + * + * @param event the document event describing the change to which to adapt the positions + */ + protected void updatePositions(DocumentEvent event) { + List list= new ArrayList(fPositionUpdaters); + Iterator e= list.iterator(); + while (e.hasNext()) { + IPositionUpdater u= (IPositionUpdater) e.next(); + u.update(event); + } + } + + /* + * @see IDocument#search + */ + public int search(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException { + + if (findString == null || findString.length() == 0) + return -1; + + ITextStore store= getStore(); + + if (startPosition < -1 || startPosition > store.getLength()) + throw new BadLocationException(); + + if (!caseSensitive) + findString= findString.toLowerCase(); + + char[] fs= new char[findString.length()]; + findString.getChars(0, fs.length, fs, 0); + + + if (forwardSearch) { + if (startPosition == -1) + startPosition= 0; + int end= getLength(); + while (startPosition < end) { + int pos= indexOf(store, fs, startPosition, caseSensitive); + if (!wholeWord || pos == -1 || isWholeWord(store, pos, pos + fs.length)) { + return pos; + } + startPosition= pos + 1; + } + } else { + if (startPosition == -1) + startPosition= getLength(); + while (startPosition >= 0) { + int pos= lastIndexOf(store, fs, startPosition, caseSensitive); + if (!wholeWord || pos == -1 || isWholeWord(store, pos, pos + fs.length)) { + return pos; + } + startPosition= pos - 1; + } + } + return -1; + } + + /* + * Returns the first index greater than fromIndex at which str + * can be found in the store. + */ + static private int indexOf(ITextStore store, char[] str, int fromIndex, boolean caseSensitive) { + int count= store.getLength(); + + if (fromIndex >= count) + return -1; + + if (fromIndex < 0) + fromIndex= 0; + + int strLen= str.length; + if (strLen == 0) // empty string always matches + return fromIndex; + + char first= str[0]; + int i= fromIndex; + int max= count - strLen; + + restart: + while (true) { + + // Look for first character + if (caseSensitive) { + while (i <= max && store.get(i) != first) + i++; + } else { + while (i <= max && Character.toLowerCase(store.get(i)) != first) + i++; + } + + if (i > max) + return -1; + + // Found first character + int j= i + 1; + int end= j + strLen - 1; + int k= 1; + if (caseSensitive) { + while (j < end) { + if (store.get(j++) != str[k++]) { + i++; + continue restart; + } + } + } else { + while (j < end) { + if (Character.toLowerCase(store.get(j++)) != str[k++]) { + i++; + continue restart; + } + } + } + + return i; // Found + } + } + + /* + * Returns the first index smaller than fromIndex at which str + * can be found in the store. + */ + static private int lastIndexOf(ITextStore store, char[] str, int fromIndex, boolean caseSensitive) { + + if (fromIndex < 0) + return -1; + + int count= store.getLength(); + int strLen= str.length; + int rightIndex= count - strLen; + + if (fromIndex > rightIndex) + fromIndex= rightIndex; + + if (strLen == 0) // empty string always matches + return fromIndex; + + int strLastIndex= strLen - 1; + char strLastChar= str[strLastIndex]; + int min= strLen - 1; + int i= min + fromIndex; + + restart: + while (true) { + + // Look for the last character + if (caseSensitive) { + while (i >= min && store.get(i) != strLastChar) + i--; + } else { + while (i >= min && Character.toLowerCase(store.get(i)) != strLastChar) + i--; + } + + if (i < min) + return -1; + + // Found last character + int j= i - 1; + int start= j - (strLen - 1); + int k= strLastIndex - 1; + + if (caseSensitive) { + while (j > start) { + if (store.get(j--) != str[k--]) { + i--; + continue restart; + } + } + } else { + while (j > start) { + if (Character.toLowerCase(store.get(j--)) != str[k--]) { + i--; + continue restart; + } + } + } + + return start + 1; /* Found whole string. */ + } + } + + /* + * Tests if the substring is a whole word. + */ + private static boolean isWholeWord(ITextStore store, int from, int to) { + + if (from > 0) { + char ch= store.get(from-1); + if (Character.isLetterOrDigit(ch) || ch == '_') { + return false; + } + } + if (to < store.getLength()) { + char ch= store.get(to); + if (Character.isLetterOrDigit(ch) || ch == '_' ) { + return false; + } + } + return true; + } + + + // ---------- implementation of IDocumentExtension -------------- + + static private class RegisteredReplace { + IDocumentListener fOwner; + IDocumentExtension.IReplace fReplace; + + RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { + fOwner= owner; + fReplace= replace; + } + }; + + /** + * Flushs all registered post notification changes. + */ + private void flushPostNotificationChanges() { + if (fPostNotificationChanges != null) + fPostNotificationChanges.clear(); + } + + /** + * Executes all registered post notification changes. The process is + * repeated until no new post notification changes are added. + */ + private void executePostNotificationChanges() { + + if (fStoppedCount > 0) + return; + + while (fPostNotificationChanges != null) { + List changes= fPostNotificationChanges; + fPostNotificationChanges= null; + + Iterator e= changes.iterator(); + while (e.hasNext()) { + RegisteredReplace replace = (RegisteredReplace) e.next(); + replace.fReplace.perform(this, replace.fOwner); + } + } + } + + /* + * @see IDocumentExtension#registerPostNotificationReplace(IDocumentListener, IReplace) + */ + public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { + if (fPostNotificationChanges == null) + fPostNotificationChanges= new ArrayList(1); + fPostNotificationChanges.add(new RegisteredReplace(owner, replace)); + } + + /* + * @see IDocumentExtension#stopPostNotificationProcessing() + */ + public void stopPostNotificationProcessing() { + ++ fStoppedCount; + } + + /* + * @see IDocumentExtension#resumePostNotificationProcessing() + */ + public void resumePostNotificationProcessing() { + -- fStoppedCount; + if (fStoppedCount == 0 && fReentranceCount == 0) + executePostNotificationChanges(); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CPresentationReconciler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CPresentationReconciler.java new file mode 100644 index 00000000000..72c78f3b629 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CPresentationReconciler.java @@ -0,0 +1,436 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.IDocumentPartitioningListener; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.TypedPosition; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.jface.util.Assert; + + + +/** + * Standard implementation of IPresentationReconciler. + * This implementation assumes that the tasks performed by its + * presentation damagers and repairers are lightweight and of low cost. + * This presentation reconciler runs in the UI thread and always repairs + * the complete damage caused by a document change rather than just the + * portion overlapping with the viewer's viewport.

+ * Usually, clients instantiate this class and configure it before using it. + */ +public class CPresentationReconciler implements IPresentationReconciler { + + protected final static String TRACKED_PARTITION= "__reconciler_tracked_partition"; //$NON-NLS-1$ + + + /** + * Internal listener class. + */ + class InternalListener implements ITextInputListener, IDocumentListener, ITextListener, + IDocumentPartitioningListener, IDocumentPartitioningListenerExtension { + + /* + * @see ITextInputListener#inputDocumentAboutToBeChanged + */ + public void inputDocumentAboutToBeChanged(IDocument oldDocument, IDocument newDocument) { + if (oldDocument != null) { + try { + + fViewer.removeTextListener(this); + oldDocument.removeDocumentListener(this); + oldDocument.removeDocumentPartitioningListener(this); + + oldDocument.removePositionUpdater(fPositionUpdater); + oldDocument.removePositionCategory(fPositionCategory); + + } catch (BadPositionCategoryException x) { + // should not happend for former input documents; + } + } + } + + /* + * @see ITextInputListener#inputDocumenChanged + */ + public void inputDocumentChanged(IDocument oldDocument, IDocument newDocument) { + if (newDocument != null) { + + newDocument.addPositionCategory(fPositionCategory); + newDocument.addPositionUpdater(fPositionUpdater); + + newDocument.addDocumentPartitioningListener(this); + newDocument.addDocumentListener(this); + fViewer.addTextListener(this); + + setDocumentToDamagers(newDocument); + setDocumentToRepairers(newDocument); + processDamage(new Region(0, newDocument.getLength()), newDocument); + } + } + + /* + * @see IDocumentPartitioningListener#documentPartitioningChanged + */ + public void documentPartitioningChanged(IDocument document) { + fDocumentPartitioningChanged= true; + } + + /* + * @see IDocumentPartitioningListenerExtension#documentPartitioningChanged + */ + public void documentPartitioningChanged(IDocument document, IRegion changedRegion) { + fDocumentPartitioningChanged= true; + fChangedDocumentPartitions= changedRegion; + } + + /* + * @see IDocumentListener#documentAboutToBeChanged + */ + public void documentAboutToBeChanged(DocumentEvent e) { + try { + int offset= e.getOffset() + e.getLength(); + fRememberedPosition= new TypedPosition(e.getDocument().getPartition(offset)); + e.getDocument().addPosition(fPositionCategory, fRememberedPosition); + } catch (BadLocationException x) { + // can not happen + } catch (BadPositionCategoryException x) { + // should not happen on input elements + } + } + + /* + * @see IDocumentListener#documentChanged + */ + public void documentChanged(DocumentEvent e) { + try { + e.getDocument().removePosition(fPositionCategory, fRememberedPosition); + } catch (BadPositionCategoryException x) { + // can not happen on input documents + } + } + + /* + * @see ITextListener#textChanged + */ + public void textChanged(TextEvent e) { + + DocumentEvent de= e.getDocumentEvent(); + + if (de == null) { + + IDocument d= fViewer.getDocument(); + processDamage(new Region(0, d.getLength()), d); + + } else { + + IRegion damage= getDamage(de); + if (damage != null) + processDamage(damage, de.getDocument()); + } + + fDocumentPartitioningChanged= false; + fChangedDocumentPartitions= null; + } + }; + + /** The map of presentation damagers */ + private Map fDamagers; + /** The map of presentation repairers */ + private Map fRepairers; + + private ITextViewer fViewer; + + private InternalListener fInternalListener= new InternalListener(); + + private String fPositionCategory; + private IPositionUpdater fPositionUpdater; + private TypedPosition fRememberedPosition; + + private boolean fDocumentPartitioningChanged= false; + private IRegion fChangedDocumentPartitions= null; + + + /** + * Creates a new presentation reconciler. There are no damagers or repairers + * registered with this reconciler. + */ + public CPresentationReconciler() { + super(); + fPositionCategory= TRACKED_PARTITION + hashCode(); + fPositionUpdater= new DefaultPositionUpdater(fPositionCategory); + } + + /** + * Registers a given presentation damager for a particular content type. + * If there is already a damager registered for this type, the new damager + * is registered instead of the old one. + * + * @param damager the presentation damager to register, or null to remove an existing one + * @param contentType the content type under which to register + */ + public void setDamager(IPresentationDamager damager, String contentType) { + + Assert.isNotNull(contentType); + + if (fDamagers == null) + fDamagers= new HashMap(); + + if (damager == null) + fDamagers.remove(contentType); + else + fDamagers.put(contentType, damager); + } + + /** + * Registers a given presentation repairer for a particular content type. + * If there is already a repairer registered for this type, the new repairer + * is registered instead of the old one. + * + * @param repairer the presentation repairer to register, or null to remove an existing one + * @param contentType the content type under which to register + */ + public void setRepairer(IPresentationRepairer repairer, String contentType) { + + Assert.isNotNull(contentType); + + if (fRepairers == null) + fRepairers= new HashMap(); + + if (repairer == null) + fRepairers.remove(contentType); + else + fRepairers.put(contentType, repairer); + } + + /* + * @see IPresentationReconciler#install + */ + public void install(ITextViewer viewer) { + Assert.isNotNull(viewer); + + fViewer= viewer; + fViewer.addTextInputListener(fInternalListener); + } + + /* + * @see IPresentationReconciler#uninstall + */ + public void uninstall() { + fViewer.removeTextInputListener(fInternalListener); + } + + /* + * @see IPresentationReconciler#getDamager + */ + public IPresentationDamager getDamager(String contentType) { + + if (fDamagers == null) + return null; + + return (IPresentationDamager) fDamagers.get(contentType); + } + + /* + * @see IPresentationReconciler#getRepairer + */ + public IPresentationRepairer getRepairer(String contentType) { + + if (fRepairers == null) + return null; + + return (IPresentationRepairer) fRepairers.get(contentType); + } + + /** + * Informs all registed damagers about the document on which they will work. + * + * @param document the document on which to work + */ + private void setDocumentToDamagers(IDocument document) { + if (fDamagers != null) { + Iterator e= fDamagers.values().iterator(); + while (e.hasNext()) { + IPresentationDamager damager= (IPresentationDamager) e.next(); + damager.setDocument(document); + } + } + } + + /** + * Informs all registed repairers about the document on which they will work. + * + * @param document the document on which to work + */ + private void setDocumentToRepairers(IDocument document) { + if (fRepairers != null) { + Iterator e= fRepairers.values().iterator(); + while (e.hasNext()) { + IPresentationRepairer repairer= (IPresentationRepairer) e.next(); + repairer.setDocument(document); + } + } + } + + /** + * Constructs a "repair description" for the given damage and returns + * this description as a text presentation. For this, it queries the + * partitioning of the damage region and asks for each partition an + * appropriate presentation repairer to construct the "repair description" + * for this partition. + * + * @param damage the damage to be repaired + * @param document the document whose presentation must be repaired + * @return the presentation repair descritption as text presentation + */ + private TextPresentation createPresentation(IRegion damage, IDocument document) { + try { + + TextPresentation presentation= new TextPresentation(); + + ITypedRegion[] partitioning= document.computePartitioning(damage.getOffset(), damage.getLength()); + for (int i= 0; i < partitioning.length; i++) { + ITypedRegion r= partitioning[i]; + IPresentationRepairer repairer= getRepairer(r.getType()); + if (repairer != null) + repairer.createPresentation(presentation, r); + } + + return presentation; + + } catch (BadLocationException x) { + } + + return null; + } + + + /** + * Checks for the first and the last affected partition and calls their damagers. + * Invalidates everything from the start of the damage for the first partition + * until the end of the damage for the last partition. + * + * @param e the event describing the document change + * @return the damaged caused by the change + */ + private IRegion getDamage(DocumentEvent e) { + + IRegion damage= null; + + try { + + ITypedRegion partition= e.getDocument().getPartition(e.getOffset()); + IPresentationDamager damager= getDamager(partition.getType()); + if (damager == null) + return null; + + IRegion r= damager.getDamageRegion(partition, e, fDocumentPartitioningChanged); + + if (!fDocumentPartitioningChanged) { + damage= r; + } else { + + int damageEnd= getDamageEndOffset(e); + + int parititionDamageEnd= -1; + if (fChangedDocumentPartitions != null) + parititionDamageEnd= fChangedDocumentPartitions.getOffset() + fChangedDocumentPartitions.getLength(); + + int end= Math.max(damageEnd, parititionDamageEnd); + + damage= end == -1 ? r : new Region(r.getOffset(), end - r.getOffset()); + } + + } catch (BadLocationException x) { + } + + return damage; + } + + /** + * Returns the end offset of the damage. If a partition has been splitted by + * the given document event also the second half of the original + * partition must be considered. This is achieved by using the remembered + * partition range. + * + * @param e the event describing the change + * @return the damage end offset (excluding) + * @exception BadLocationException if method accesses invalid offset + */ + private int getDamageEndOffset(DocumentEvent e) throws BadLocationException { + + IDocument d= e.getDocument(); + + int length= 0; + if (e.getText() != null) { + length= e.getText().length(); + if (length > 0) + -- length; + } + + ITypedRegion partition= d.getPartition(e.getOffset() + length); + int endOffset= partition.getOffset() + partition.getLength(); + if (endOffset == e.getOffset()) + return -1; + + int end= fRememberedPosition.getOffset() + fRememberedPosition.getLength(); + if (endOffset < end) + partition= d.getPartition(end); + + IPresentationDamager damager= getDamager(partition.getType()); + if (damager == null) + return -1; + + IRegion r= damager.getDamageRegion(partition, e, fDocumentPartitioningChanged); + + return r.getOffset() + r.getLength(); + } + + /** + * Processes the given damage. + * @param damage the damage to be repaired + * @param document the document whose presentation must be repaired + */ + private void processDamage(IRegion damage, IDocument document) { + if (damage != null && damage.getLength() > 0) { + TextPresentation p= createPresentation(damage, document); + if (p != null && !p.isEmpty()) + applyTextRegionCollection(p); + } + } + + /** + * Applies the given text presentation to the text viewer the presentation + * reconciler is installed on. + * + * @param presentation the text presentation to be applied to the text viewer + */ + private void applyTextRegionCollection(TextPresentation presentation) { + fViewer.changeTextPresentation(presentation, false); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedDamagerRepairer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedDamagerRepairer.java new file mode 100644 index 00000000000..5267fcd7d8f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedDamagerRepairer.java @@ -0,0 +1,209 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.custom.StyleRange; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.util.Assert; + + +/** + * A standard implementation of a syntax driven presentation damager + * and presentation repairer. It uses a rule based scanner to scan + * the document and to determine its damage and new text presentation. + * The tokens returned by the rules the scanner is configured with + * are supposed to return text attributes as their data. + * + * @see IRule + * @see RuleBasedScanner + */ +public class CRuleBasedDamagerRepairer implements IPresentationDamager, IPresentationRepairer { + + /** The document this object works on */ + protected IDocument fDocument; + /** The scanner it uses */ + protected RuleBasedScanner fScanner; + /** The default text attribute if non is returned as data by the current token */ + protected TextAttribute fDefaultTextAttribute; + + /** + * Creates a damager/repairer that uses the given scanner and returns the given default + * text attribute if the current token does not carry a text attribute. + * + * @param scanner the rule based scanner to be used + * @param defaultTextAttribute the text attribute to be returned if non is specified by the current token, + * may not be null + * + * @deprecated use RuleBasedDamagerRepairer(RuleBasedScanner) instead + */ + public CRuleBasedDamagerRepairer(RuleBasedScanner scanner, TextAttribute defaultTextAttribute) { + + Assert.isNotNull(defaultTextAttribute); + + fScanner= scanner; + fDefaultTextAttribute= defaultTextAttribute; + } + + /** + * Creates a damager/repairer that uses the given scanner. The scanner may not be null + * and is assumed to return only token that carry text attributes. + * + * @param scanner the rule based scanner to be used, may not be null + */ + public CRuleBasedDamagerRepairer(RuleBasedScanner scanner) { + + Assert.isNotNull(scanner); + + fScanner= scanner; + } + + /* + * @see IPresentationDamager#setDocument + * @see IPresentationRepairer#setDocument + */ + public void setDocument(IDocument document) { + fDocument= document; + } + + + //---- IPresentationDamager + + /** + * Returns the end offset of the line that contains the specified offset or + * if the offset is inside a line delimiter, the end offset of the next line. + * + * @param offset the offset whose line end offset must be computed + * @return the line end offset for the given offset + * @exception BadLocationException if offset is invalid in the current document + */ + protected int endOfLineOf(int offset) throws BadLocationException { + + IRegion info= fDocument.getLineInformationOfOffset(offset); + if (offset <= info.getOffset() + info.getLength()) + return info.getOffset() + info.getLength(); + + int line= fDocument.getLineOfOffset(offset); + try { + info= fDocument.getLineInformation(line + 1); + return info.getOffset() + info.getLength(); + } catch (BadLocationException x) { + return fDocument.getLength(); + } + } + + /* + * @see IPresentationDamager#getDamageRegion + */ + public IRegion getDamageRegion(ITypedRegion partition, DocumentEvent e, boolean documentPartitioningChanged) { + + if (!documentPartitioningChanged) { + try { + + IRegion info= fDocument.getLineInformationOfOffset(e.getOffset()); + int start= Math.max(partition.getOffset(), info.getOffset()); + + int end= e.getOffset() + (e.getText() == null ? e.getLength() : e.getText().length()); + + if (info.getOffset() <= end && end <= info.getOffset() + info.getLength()) { + // optimize the case of the same line + end= info.getOffset() + info.getLength(); + } else + end= endOfLineOf(end); + + end= Math.min(partition.getOffset() + partition.getLength(), end); + return new Region(start, end - start); + + } catch (BadLocationException x) { + } + } + + return partition; + } + + //---- IPresentationRepairer + + /* + * @see IPresentationRepairer#createPresentation + */ + public void createPresentation(TextPresentation presentation, ITypedRegion region) { + + if (fScanner == null) { + // will be removed if deprecated constructor will be removed + addRange(presentation, region.getOffset(), region.getLength(), fDefaultTextAttribute); + return; + } + + int lastStart= region.getOffset(); + int length= 0; + IToken lastToken= Token.UNDEFINED; + TextAttribute lastAttribute= getTokenTextAttribute(lastToken); + + fScanner.setRange(fDocument, lastStart, region.getLength()); + + while (true) { + IToken token= fScanner.nextToken(); + if (token.isEOF()) + break; + + TextAttribute attribute= getTokenTextAttribute(token); + if (lastAttribute != null && lastAttribute.equals(attribute)) { + length += fScanner.getTokenLength(); + } else { + addRange(presentation, lastStart, length, lastAttribute); + lastToken= token; + lastAttribute= attribute; + lastStart= fScanner.getTokenOffset(); + length= fScanner.getTokenLength(); + } + } + + addRange(presentation, lastStart, length, lastAttribute); + } + + /** + * Returns a text attribute encoded in the given token. If the token's + * data is not null and a text attribute it is assumed that + * it is the encoded text attribute. It returns the default text attribute + * if there is no encoded text attribute found. + * + * @param token the token whose text attribute is to be determined + * @return the token's text attribute + */ + protected TextAttribute getTokenTextAttribute(IToken token) { + Object data= token.getData(); + if (data instanceof TextAttribute) + return (TextAttribute) data; + return fDefaultTextAttribute; + } + + /** + * Adds style information to the given text presentation. + * + * @param presentation the text presentation to be extended + * @param offset the offset of the range to be styled + * @param length the length of the range to be styled + * @param attr the attribute describing the style of the range to be styled + */ + protected void addRange(TextPresentation presentation, int offset, int length, TextAttribute attr) { + if (attr != null) + presentation.addStyleRange(new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), attr.getStyle())); + } +} + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedPartitioner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedPartitioner.java new file mode 100644 index 00000000000..fedbaf5d783 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/CRuleBasedPartitioner.java @@ -0,0 +1,500 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentPartitioner; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TypedPosition; +import org.eclipse.jface.text.TypedRegion; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.util.Assert; + + + +/** + * A standard implementation of a syntax driven document partitioner. + * It uses a rule based scanner to scan the document and to determine + * the document's partitioning. The tokens returned by the rules the + * scanner is configured with are supposed to return the partition type + * as their data. The partitoner remembers the document's partitions + * in the document itself rather than maintaining its own data structure. + * + * @see IRule + * @see RuleBasedScanner + */ +public class CRuleBasedPartitioner implements IDocumentPartitioner, IDocumentPartitionerExtension { + + /** The position category this partitioner uses to store the document's partitioning information */ + public final static String CONTENT_TYPES_CATEGORY= "__content_types_category"; //$NON-NLS-1$ + + + /** The partitioner's scanner */ + protected RuleBasedScanner fScanner; + /** The legal content types of this partitioner */ + protected String[] fLegalContentTypes; + /** The partitioner's document */ + protected IDocument fDocument; + /** The document length before a document change occured */ + protected int fPreviousDocumentLength; + /** The position updater used to for the default updating of partitions */ + protected DefaultPositionUpdater fPositionUpdater= new DefaultPositionUpdater(CONTENT_TYPES_CATEGORY); + /** The offset at which the first changed partition starts */ + protected int fStartOffset; + /** The offset at which the last changed partition ends */ + protected int fEndOffset; + /**The offset at which a partition has been deleted */ + protected int fDeleteOffset; + + + /** + * Creates a new partitioner that uses the given scanner and may return + * partitions of the given legal content types. + * + * @param scanner the scanner this partitioner is supposed to use + * @param legalContentTypes the legal content types of this partitioner + */ + public CRuleBasedPartitioner(RuleBasedScanner scanner, String[] legalContentTypes) { + fScanner= scanner; + fLegalContentTypes= legalContentTypes; + } + + /* + * @see IDocumentPartitioner#connect + */ + public void connect(IDocument document) { + Assert.isNotNull(document); + Assert.isTrue(!document.containsPositionCategory(CONTENT_TYPES_CATEGORY)); + + fDocument= document; + fDocument.addPositionCategory(CONTENT_TYPES_CATEGORY); + + initialize(); + } + + /** + * Performs the initial partitioning of the partitioner's document. + */ + protected void initialize() { + + fScanner.setRange(fDocument, 0, fDocument.getLength()); + + try { + IToken token= fScanner.nextToken(); + while (!token.isEOF()) { + + String contentType= getTokenContentType(token); + + if (isSupportedContentType(contentType)) { + TypedPosition p= new TypedPosition(fScanner.getTokenOffset(), fScanner.getTokenLength(), contentType); + fDocument.addPosition(CONTENT_TYPES_CATEGORY, p); + } + + token= fScanner.nextToken(); + } + } catch (BadLocationException x) { + // cannot happen as offsets come from scanner + } catch (BadPositionCategoryException x) { + // cannot happen if document has been connected before + } + } + + /* + * @see IDocumentPartitioner#disconnect + */ + public void disconnect() { + + Assert.isTrue(fDocument.containsPositionCategory(CONTENT_TYPES_CATEGORY)); + + try { + fDocument.removePositionCategory(CONTENT_TYPES_CATEGORY); + } catch (BadPositionCategoryException x) { + // can not happen because of Assert + } + } + + /* + * @see IDocumentPartitioner#documentAboutToBeChanged + */ + public void documentAboutToBeChanged(DocumentEvent e) { + + Assert.isTrue(e.getDocument() == fDocument); + + fPreviousDocumentLength= e.getDocument().getLength(); + fStartOffset= -1; + fEndOffset= -1; + fDeleteOffset= -1; + } + + /* + * @see IDocumentPartitioner#documentChanged + */ + public boolean documentChanged(DocumentEvent e) { + IRegion region= documentChanged2(e); + return (region != null); + } + + private void rememberRegion(int offset, int length) { + // remember start offset + if (fStartOffset == -1) + fStartOffset= offset; + else if (offset < fStartOffset) + fStartOffset= offset; + + // remember end offset + int endOffset= offset + length; + if (fEndOffset == -1) + fEndOffset= endOffset; + else if (endOffset > fEndOffset) + fEndOffset= endOffset; + } + + private void rememberDeletedOffset(int offset) { + fDeleteOffset= offset; + } + + private IRegion createRegion() { + if (fDeleteOffset == -1) { + if (fStartOffset == -1 || fEndOffset == -1) + return null; + return new Region(fStartOffset, fEndOffset - fStartOffset); + } else if (fStartOffset == -1 || fEndOffset == -1) { + return new Region(fDeleteOffset, 0); + } else { + int offset= Math.min(fDeleteOffset, fStartOffset); + int endOffset= Math.max(fDeleteOffset, fEndOffset); + return new Region(offset, endOffset - offset); + } + } + + /* + * @see IDocumentPartitionerExtension#documentChanged2(DocumentEvent) + */ + public IRegion documentChanged2(DocumentEvent e) { + + try { + + IDocument d= e.getDocument(); + Position[] category= d.getPositions(CONTENT_TYPES_CATEGORY); + int first= 0; + int reparseStart= 0; + int originalSize= category.length; + + if (originalSize > 0) { + + /* + * determine character position at which the scanner starts: + * first position behind the last non-default partition the actual position is not involved with + */ + + first= d.computeIndexInCategory(CONTENT_TYPES_CATEGORY, e.getOffset()); + + Position p= null; + do { + --first; + if (first < 0) + break; + + p= category[first]; + + } while (p.overlapsWith(e.getOffset(), e.getLength()) || + (e.getOffset() == fPreviousDocumentLength && + (p.getOffset() + p.getLength() == fPreviousDocumentLength))); + + fPositionUpdater.update(e); + for (int i= 0; i < category.length; i++) { + p= category[i]; + if (p.isDeleted) { + rememberDeletedOffset(e.getOffset()); + break; + } + } + category= d.getPositions(CONTENT_TYPES_CATEGORY); + + if (first >= 0) { + p= category[first]; + reparseStart= p.getOffset() + p.getLength(); + } + + ++first; + } + + fScanner.setRange(d, reparseStart, d.getLength()); + + int lastScannedPosition= reparseStart; + IToken token= fScanner.nextToken(); + + while (!token.isEOF()) { + + + String contentType= getTokenContentType(token); + + if (!isSupportedContentType(contentType)) { + token= fScanner.nextToken(); + continue; + } + + int start= fScanner.getTokenOffset(); + int length= fScanner.getTokenLength(); + + lastScannedPosition= start + length - 1; + + // remove all affected positions + while (first < category.length) { + TypedPosition p= (TypedPosition) category[first]; + if (lastScannedPosition >= p.offset + p.length || + (p.overlapsWith(start, length) && + (!d.containsPosition(CONTENT_TYPES_CATEGORY, start, length) || + !contentType.equals(p.getType())))) { + + rememberRegion(p.offset, p.length); + d.removePosition(CONTENT_TYPES_CATEGORY, p); + ++ first; + + } else + break; + } + + // if position already exists we are done + if (d.containsPosition(CONTENT_TYPES_CATEGORY, start, length)) + return createRegion(); + + // insert the new type position + try { + d.addPosition(CONTENT_TYPES_CATEGORY, new TypedPosition(start, length, contentType)); + rememberRegion(start, length); + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + + token= fScanner.nextToken(); + } + + + // remove all positions behind lastScannedPosition since there aren't any further types + TypedPosition p; + first= d.computeIndexInCategory(CONTENT_TYPES_CATEGORY, lastScannedPosition); + while (first < category.length) { + p= (TypedPosition) category[first++]; + d.removePosition(CONTENT_TYPES_CATEGORY, p); + rememberRegion(p.offset, p.length); + } + + } catch (BadPositionCategoryException x) { + // should never happen on connected documents + } catch (BadLocationException x) { + } + + return createRegion(); + } + + + /** + * Returns the position in the partitoner's position category which is + * close to the given offset. This is, the position has either an offset which + * is the same as the given offset or an offset which is smaller than the given + * offset. This method profits from the knowledge that a partitioning is + * a ordered set of disjoint position. + * + * @param offset the offset for which to search the closest position + * @return the closest position in the partitioner's category + */ + protected TypedPosition findClosestPosition(int offset) { + + try { + + int index= fDocument.computeIndexInCategory(CONTENT_TYPES_CATEGORY, offset); + Position[] category= fDocument.getPositions(CONTENT_TYPES_CATEGORY); + + if (category.length == 0) + return null; + + if (index < category.length) { + if (offset == category[index].offset) + return (TypedPosition) category[index]; + } + + if (index > 0) + index--; + + return (TypedPosition) category[index]; + + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + + return null; + } + + + /* + * @see IDocumentPartitioner#getContentType + */ + public String getContentType(int offset) { + + TypedPosition p= findClosestPosition(offset); + if (p != null && p.includes(offset)) + return p.getType(); + + return IDocument.DEFAULT_CONTENT_TYPE; + } + + /* + * @see IDocumentPartitioner#getPartition + */ + public ITypedRegion getPartition(int offset) { + + try { + + Position[] category = fDocument.getPositions(CONTENT_TYPES_CATEGORY); + + if (category == null || category.length == 0) + return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE); + + int index= fDocument.computeIndexInCategory(CONTENT_TYPES_CATEGORY, offset); + + if (index < category.length) { + + TypedPosition next= (TypedPosition) category[index]; + + if (offset == next.offset) + return new TypedRegion(next.getOffset(), next.getLength(), next.getType()); + + if (index == 0) + return new TypedRegion(0, next.offset, IDocument.DEFAULT_CONTENT_TYPE); + + TypedPosition previous= (TypedPosition) category[index - 1]; + if (previous.includes(offset)) + return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType()); + + int endOffset= previous.getOffset() + previous.getLength(); + return new TypedRegion(endOffset, next.getOffset() - endOffset, IDocument.DEFAULT_CONTENT_TYPE); + } + + TypedPosition previous= (TypedPosition) category[category.length - 1]; + if (previous.includes(offset)) + return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType()); + + int endOffset= previous.getOffset() + previous.getLength(); + return new TypedRegion(endOffset, fDocument.getLength() - endOffset, IDocument.DEFAULT_CONTENT_TYPE); + + } catch (BadPositionCategoryException x) { + } catch (BadLocationException x) { + } + + return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE); + } + + /* + * @see IDocumentPartitioner#computePartitioning + */ + public ITypedRegion[] computePartitioning(int offset, int length) { + + List list= new ArrayList(); + + try { + + int endOffset= offset + length; + + Position[] category= fDocument.getPositions(CONTENT_TYPES_CATEGORY); + + TypedPosition previous= null, current= null; + int start, end, gapOffset; + Position gap= null; + + for (int i= 0; i < category.length; i++) { + + current= (TypedPosition) category[i]; + + gapOffset= (previous != null) ? previous.getOffset() + previous.getLength() : 0; + gap= new Position(gapOffset, current.getOffset() - gapOffset); + if (gap.getLength() > 0 && gap.overlapsWith(offset, length)) { + start= Math.max(offset, gapOffset); + end= Math.min(endOffset, gap.getOffset() + gap.getLength()); + list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE)); + } + + if (current.overlapsWith(offset, length)) { + start= Math.max(offset, current.getOffset()); + end= Math.min(endOffset, current.getOffset() + current.getLength()); + list.add(new TypedRegion(start, end - start, current.getType())); + } + + previous= current; + } + + if (previous != null) { + gapOffset= previous.getOffset() + previous.getLength(); + gap= new Position(gapOffset, fDocument.getLength() - gapOffset); + if (gap.getLength() > 0 && gap.overlapsWith(offset, length)) { + start= Math.max(offset, gapOffset); + end= Math.min(endOffset, fDocument.getLength()); + list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE)); + } + } + + if (list.isEmpty()) + list.add(new TypedRegion(offset, length, IDocument.DEFAULT_CONTENT_TYPE)); + + } catch (BadPositionCategoryException x) { + } + + TypedRegion[] result= new TypedRegion[list.size()]; + list.toArray(result); + return result; + } + + /* + * @see IDocumentPartitioner#getLegalContentTypes + */ + public String[] getLegalContentTypes() { + return fLegalContentTypes; + } + + /** + * Returns whether the given type is one of the legal content types. + * + * @param contentType the content type to check + * @return true if the content type is a legal content type + */ + protected boolean isSupportedContentType(String contentType) { + if (contentType != null) { + for (int i= 0; i < fLegalContentTypes.length; i++) { + if (fLegalContentTypes[i].equals(contentType)) + return true; + } + } + + return false; + } + + /** + * Returns a content type encoded in the given token. If the token's + * data is not null and a string it is assumed that + * it is the encoded content type. + * + * @param token the token whose content type is to be determined + * @return the token's content type + */ + protected String getTokenContentType(IToken token) { + Object data= token.getData(); + if (data instanceof String) + return (String) data; + return null; + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentExtension.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentExtension.java new file mode 100644 index 00000000000..a3a50f49ddc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentExtension.java @@ -0,0 +1,57 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; + + +/** + * For internal use only. Not API.

+ * A document extension is for extending + * IDocument instances with new functionality. +*/ +public interface IDocumentExtension { + + /** + * Interface for a post notification document change. + */ + interface IReplace { + + /** + * Executes the replace operation of the given document. + * @param document the document to be changed + * @param owner the owner of this replace object + */ + void perform(IDocument document, IDocumentListener owner); + }; + + /** + * Callback for document listeners to achieve a post notification + * change of the document notifying them. + * + * @param owner the owner of the replace object + * @param the replace to be executed + * @exception UnsupportedOperationException if registerPostNotificationReplace + * is not supported by this document + */ + void registerPostNotificationReplace(IDocumentListener owner, IReplace replace) throws UnsupportedOperationException; + + /** + * Stops the processing of registered post notification replaces until + * resumePostNotificationProcessing is called. + */ + void stopPostNotificationProcessing(); + + /** + * Resumes the processing of post notification replaces. If the queue of registered + * IReplace objects is not empty, they are immediately processed + * if the document is not inside a replace operation or directly after the replace + * operation otherwise. + */ + void resumePostNotificationProcessing(); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitionerExtension.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitionerExtension.java new file mode 100644 index 00000000000..62ef3bf12c1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitionerExtension.java @@ -0,0 +1,34 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IRegion; + + +/** + * For internal use only. Not API.

+ * A document partitioner extension is for extending + * IDocumentPartitioner instances with new + * or revised functionality. +*/ +public interface IDocumentPartitionerExtension { + + /** + * The document has been changed. The partitioner updates + * the document's partitioning and returns in which region the + * partition type has been changed. This method always returns + * the surrounding region. Will be called by the connected document + * and is not intended to be used by clients other than the connected + * document. + * + * @param event the event describing the document change + * @return the region of the document in which the partition type changed + */ + IRegion documentChanged2(DocumentEvent event); +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitioningListenerExtension.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitioningListenerExtension.java new file mode 100644 index 00000000000..8391fa38770 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/IDocumentPartitioningListenerExtension.java @@ -0,0 +1,31 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; + + +/** + * For internal use only. Not API.

+ * A document partitioning listener extension is for extending + * IDocumentPartitioningListener instances with new + * or revised functionality. +*/ +public interface IDocumentPartitioningListenerExtension { + + /** + * The partitioning of the given document changed in the given range. + * + * @param document the document whose partitioning changed + * @param region the range in which the partition type changed + * + * @see IDocument#addDocumentPartitioningListener + */ + void documentPartitioningChanged(IDocument document, IRegion region); +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/ITextViewerExtension.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/ITextViewerExtension.java new file mode 100644 index 00000000000..9e92e0f9523 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/ITextViewerExtension.java @@ -0,0 +1,52 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.custom.VerifyKeyListener; + + +/** + * A text viewer extension is for extending + * ITextViewer instances with new functionality. + */ +public interface ITextViewerExtension { + + /* + * All subsequent methods dealing with verify key listeners + * are indended to allow clients a fine grained management of + * key event consumption. Will be merged/ will replace + * the event consumer mechanism available on ITextViewer. + */ + + /** + * Inserts the verify key listener at the beginning of the viewer's + * list of verify key listeners. If the listener is already registered + * with the viewer this call moves the listener to the beginnng of + * the list. + * + * @param listener the listener to be inserted + */ + void prependVerifyKeyListener(VerifyKeyListener listener); + + /** + * Appends a verify key listener to the viewer's list of verify + * key listeners. If the listener is already registered with the viewer + * this call moves the listener to the end of the list. + * + * @param listener the listener to be added + */ + void appendVerifyKeyListener(VerifyKeyListener listener); + + /** + * Removes the verify key listener from the viewer's list of verify key listeners. + * If the listener is not registered with this viewer, this call has no effect. + * + * @param listener the listener to be removed + */ + void removeVerifyKeyListener(VerifyKeyListener listener); +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/Token.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/Token.java new file mode 100644 index 00000000000..cc5471ee2a2 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/eclipse2/Token.java @@ -0,0 +1,113 @@ +package org.eclipse.cdt.internal.ui.text.eclipse2; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.util.Assert; + + +/** + * Standard implementation of IToken. + */ +public class Token implements IToken { + + private static final int T_UNDEFINED= 0; + private static final int T_EOF= 1; + private static final int T_WHITESPACE= 2; + private static final int T_OTHER= 3; + + + /** + * Standard undefined token + */ + public static final IToken UNDEFINED= new Token(T_UNDEFINED); + /** + * Standard End Of File token + */ + public static final IToken EOF= new Token(T_EOF); + /** + * Standard whitespace token + */ + public static final IToken WHITESPACE= new Token(T_WHITESPACE); + /** + * Standard token neither undefine, whitespace, nor whitespace + * @deprecated will be removed + */ + public static final IToken OTHER= new Token(T_OTHER); + + + private int fType; + private Object fData; + + /** + * Creates a new token according to the given specification which does not + * have any data attached to it. + * + * @param type the type of the token + */ + private Token(int type) { + fType= type; + fData= null; + } + + /** + * Creates a new token which represents neither undefined, whitespace, nor EOF. + * The newly created token has the given data attached to it. + * + * @param data the data attached to the newly created token + */ + public Token(Object data) { + fType= T_OTHER; + fData= data; + } + + /** + * Reinitializes the data of this token. The token may not represent + * undefined, whitepsace, or EOF. + * + * @param the data to be attached to the token + */ + public void setData(Object data) { + Assert.isTrue(isOther()); + fData= data; + } + + /* + * @see IToken#getData() + */ + public Object getData() { + return fData; + } + + /* + * @see IToken#isOther() + */ + public boolean isOther() { + return (fType == T_OTHER); + } + + /* + * @see IToken#isEOF() + */ + public boolean isEOF() { + return (fType == T_EOF); + } + + /* + * @see IToken#isWhitespace() + */ + public boolean isWhitespace() { + return (fType == T_WHITESPACE); + } + + /* + * @see IToken#isUndefined() + */ + public boolean isUndefined() { + return (fType == T_UNDEFINED); + } +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionListener.java new file mode 100644 index 00000000000..12e3bb8de5b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionListener.java @@ -0,0 +1,31 @@ +package org.eclipse.cdt.internal.ui.text.link; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.Position; + +/** + * A listener for highlight change notification and exititing linked mode. + */ +public interface LinkedPositionListener { + + /** + * Notifies that the linked mode has been left. On success, all changes + * are kept, otherwise all changes made to the linked positions are restored + * to the state before entering linked mode. + */ + void exit(boolean success); + + /** + * Notifies the changed linked position. The listener is asked + * to reposition the caret at the given offset. + * + * @param position the linked position which initiated the change. + * @param caretOffset the caret offset relative to the position. + */ + void setCurrentPosition(Position position, int caretOffset); + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionManager.java new file mode 100644 index 00000000000..080653a7c2f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionManager.java @@ -0,0 +1,448 @@ +package org.eclipse.cdt.internal.ui.text.link; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.eclipse2.IDocumentExtension; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.TypedPosition; +import org.eclipse.jface.util.Assert; + + +/** + * This class manages linked positions in a document. Positions are linked + * by type names. If positions have the same type name, they are considered + * as linked. + * + * The manager remains active on a document until any of the following actions + * occurs: + * + *

    + *
  • A document change is performed which would invalidate any of the + * above constraints.
  • + * + *
  • The method uninstall() is called.
  • + * + *
  • Another instance of LinkedPositionManager tries to + * gain control of the same document. + *
+ */ +public class LinkedPositionManager implements IDocumentListener, IPositionUpdater { + + private static class PositionComparator implements Comparator { + /* + * @see Comparator#compare(Object, Object) + */ + public int compare(Object object0, Object object1) { + Position position0= (Position) object0; + Position position1= (Position) object1; + + return position0.getOffset() - position1.getOffset(); + } + } + + private class Replace implements IDocumentExtension.IReplace { + + private Position fReplacePosition; + private int fReplaceDeltaOffset; + private int fReplaceLength; + private String fReplaceText; + + public Replace(Position position, int deltaOffset, int length, String text) { + fReplacePosition= position; + fReplaceDeltaOffset= deltaOffset; + fReplaceLength= length; + fReplaceText= text; + } + + public void perform(IDocument document, IDocumentListener owner) { + document.removeDocumentListener(owner); + try { + document.replace(fReplacePosition.getOffset() + fReplaceDeltaOffset, fReplaceLength, fReplaceText); + } catch (BadLocationException e) { + CPlugin.log(e); + // TBD + } + document.addDocumentListener(owner); + } + } + + private static final String LINKED_POSITION= "LinkedPositionManager.linked.position"; //$NON-NLS-1$ + private static final Comparator fgPositionComparator= new PositionComparator(); + private static final Map fgActiveManagers= new HashMap(); + + private IDocument fDocument; + + private LinkedPositionListener fListener; + + /** + * Creates a LinkedPositionManager for a IDocument. + * + * @param document the document to use with linked positions. + */ + public LinkedPositionManager(IDocument document) { + Assert.isNotNull(document); + + fDocument= document; + install(); + } + + /** + * Sets a listener to notify changes of current linked position. + */ + public void setLinkedPositionListener(LinkedPositionListener listener) { + fListener= listener; + } + + /** + * Adds a linked position to the manager. + * There are the following constraints for linked positions: + * + *
    + *
  • Any two positions have spacing of at least one character. + * This implies that two positions must not overlap.
  • + * + *
  • The string at any position must not contain line delimiters.
  • + *
+ * + * @param offset the offset of the position. + * @param length the length of the position. + */ + public void addPosition(int offset, int length) throws BadLocationException { + Position[] positions= getPositions(fDocument); + + if (positions != null) { + for (int i = 0; i < positions.length; i++) + if (collides(positions[i], offset, length)) + throw new BadLocationException(LinkedPositionMessages.getString(("LinkedPositionManager.error.position.collision"))); //$NON-NLS-1$ + } + + String type= fDocument.get(offset, length); + + if (containsLineDelimiters(type)) + throw new BadLocationException(LinkedPositionMessages.getString(("LinkedPositionManager.error.contains.line.delimiters"))); //$NON-NLS-1$ + + try { + fDocument.addPosition(LINKED_POSITION, new TypedPosition(offset, length, type)); + } catch (BadPositionCategoryException e) { + CPlugin.log(e); + Assert.isTrue(false); + } + } + + /** + * Tests if a manager is already active for a document. + */ + public static boolean hasActiveManager(IDocument document) { + return fgActiveManagers.get(document) != null; + } + + private void install() { + LinkedPositionManager manager= (LinkedPositionManager) fgActiveManagers.get(fDocument); + if (manager != null) + manager.leave(true); + + fgActiveManagers.put(fDocument, this); + + fDocument.addPositionCategory(LINKED_POSITION); + fDocument.addPositionUpdater(this); + fDocument.addDocumentListener(this); + } + + /** + * Leaves the linked mode. If unsuccessful, the linked positions + * are restored to the values at the time they were added. + */ + public void uninstall(boolean success) { + fDocument.removeDocumentListener(this); + + try { + Position[] positions= getPositions(fDocument); + if ((!success) && (positions != null)) { + // restore + for (int i= 0; i != positions.length; i++) { + TypedPosition position= (TypedPosition) positions[i]; + fDocument.replace(position.getOffset(), position.getLength(), position.getType()); + } + } + + fDocument.removePositionCategory(LINKED_POSITION); + + } catch (BadLocationException e) { + CPlugin.log(e); + Assert.isTrue(false); + + } catch (BadPositionCategoryException e) { + CPlugin.log(e); + Assert.isTrue(false); + + } finally { + fDocument.removePositionUpdater(this); + fgActiveManagers.remove(fDocument); + } + } + + /** + * Returns the first linked position. + * + * @return returns null if no linked position exist. + */ + public Position getFirstPosition() { + return getNextPosition(-1); + } + + /** + * Returns the next linked position with an offset greater than offset. + * If another position with the same type and offset lower than offset + * exists, the position is skipped. + * + * @return returns null if no linked position exist. + */ + public Position getNextPosition(int offset) { + Position[] positions= getPositions(fDocument); + return findNextPosition(positions, offset); + } + + private static Position findNextPosition(Position[] positions, int offset) { + // skip already visited types + for (int i= 0; i != positions.length; i++) { + if (positions[i].getOffset() > offset) { + String type= ((TypedPosition) positions[i]).getType(); + int j; + for (j = 0; j != i; j++) + if (((TypedPosition) positions[j]).getType().equals(type)) + break; + + if (j == i) + return positions[i]; + } + } + + return null; + } + + /** + * Returns the position with the greatest offset smaller than offset. + * + * @return returns null if no linked position exist. + */ + public Position getPreviousPosition(int offset) { + Position[] positions= getPositions(fDocument); + if (positions == null) + return null; + + Position lastPosition= null; + Position position= getFirstPosition(); + + while ((position != null) && (position.getOffset() < offset)) { + lastPosition= position; + position= findNextPosition(positions, position.getOffset()); + } + + return lastPosition; + } + + private static Position[] getPositions(IDocument document) { + try { + Position[] positions= document.getPositions(LINKED_POSITION); + Arrays.sort(positions, fgPositionComparator); + return positions; + + } catch (BadPositionCategoryException e) { + CPlugin.log(e); + Assert.isTrue(false); + } + + return null; + } + + public static boolean includes(Position position, int offset, int length) { + return + (offset >= position.getOffset()) && + (offset + length <= position.getOffset() + position.getLength()); + } + + public static boolean excludes(Position position, int offset, int length) { + return + (offset + length <= position.getOffset()) || + (position.getOffset() + position.getLength() <= offset); + } + + /* + * Collides if spacing if positions intersect each other or are adjacent. + */ + private static boolean collides(Position position, int offset, int length) { + return + (offset <= position.getOffset() + position.getLength()) && + (position.getOffset() <= offset + length); + } + + private void leave(boolean success) { + uninstall(success); + + if (fListener != null) + fListener.exit(success); + } + + /* + * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent) + */ + public void documentAboutToBeChanged(DocumentEvent event) { + IDocument document= event.getDocument(); + + Position[] positions= getPositions(document); + Position position= findCurrentEditablePosition(positions, event.getOffset()); + + // modification outside editable position + if (position == null) { + position= findCurrentPosition(positions, event.getOffset()); + + // modification outside any position + if (position == null) { + // check for destruction of constraints (spacing of at least 1) + if ((event.getText().length() == 0) && + (findCurrentPosition(positions, event.getOffset()) != null) && + (findCurrentPosition(positions, event.getOffset() + event.getLength()) != null)) + { + leave(true); + } + + // modification intersects non-editable position + } else { + leave(true); + } + + // modification intersects editable position + } else { + // modificaction inside editable position + if (includes(position, event.getOffset(), event.getLength())) { + if (containsLineDelimiters(event.getText())) + leave(true); + + // modificaction exceeds editable position + } else { + leave(true); + } + } + } + + /* + * @see IDocumentListener#documentChanged(DocumentEvent) + */ + public void documentChanged(DocumentEvent event) { + IDocument document= event.getDocument(); + + Position[] positions= getPositions(document); + TypedPosition currentPosition= (TypedPosition) findCurrentEditablePosition(positions, event.getOffset()); + + // ignore document changes (assume it won't invalidate constraints) + if (currentPosition == null) + return; + + int deltaOffset= event.getOffset() - currentPosition.getOffset(); + + if (fListener != null) + fListener.setCurrentPosition(currentPosition, deltaOffset + event.getText().length()); + + for (int i= 0; i != positions.length; i++) { + TypedPosition p= (TypedPosition) positions[i]; + + if (p.getType().equals(currentPosition.getType()) && !p.equals(currentPosition)) { + Replace replace= new Replace(p, deltaOffset, event.getLength(), event.getText()); + ((IDocumentExtension) document).registerPostNotificationReplace(this, replace); + } + } + } + + /* + * @see IPositionUpdater#update(DocumentEvent) + */ + public void update(DocumentEvent event) { + int deltaLength= event.getText().length() - event.getLength(); + + Position[] positions= getPositions(event.getDocument()); + TypedPosition currentPosition= (TypedPosition) findCurrentPosition(positions, event.getOffset()); + + // document change outside positions + if (currentPosition == null) { + + for (int i= 0; i != positions.length; i++) { + TypedPosition position= (TypedPosition) positions[i]; + int offset= position.getOffset(); + + if (offset >= event.getOffset()) + position.setOffset(offset + deltaLength); + } + + // document change within a position + } else { + int length= currentPosition.getLength(); + + for (int i= 0; i != positions.length; i++) { + TypedPosition position= (TypedPosition) positions[i]; + int offset= position.getOffset(); + + if (position.equals(currentPosition)) { + position.setLength(length + deltaLength); + } else if (offset > currentPosition.getOffset()) { + position.setOffset(offset + deltaLength); + } + } + } + } + + private static Position findCurrentPosition(Position[] positions, int offset) { + for (int i= 0; i != positions.length; i++) + if (includes(positions[i], offset, 0)) + return positions[i]; + + return null; + } + + private static Position findCurrentEditablePosition(Position[] positions, int offset) { + Position position= positions[0]; + + while ((position != null) && !includes(position, offset, 0)) + position= findNextPosition(positions, position.getOffset()); + + return position; + } + + private boolean containsLineDelimiters(String string) { + String[] delimiters= fDocument.getLegalLineDelimiters(); + + for (int i= 0; i != delimiters.length; i++) + if (string.indexOf(delimiters[i]) != -1) + return true; + + return false; + } + + /** + * Test if ok to modify through UI. + */ + public boolean anyPositionIncludes(int offset, int length) { + Position[] positions= getPositions(fDocument); + + Position position= findCurrentEditablePosition(positions, offset); + if (position == null) + return false; + + return includes(position, offset, length); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.java new file mode 100644 index 00000000000..67439db4171 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.java @@ -0,0 +1,44 @@ +package org.eclipse.cdt.internal.ui.text.link; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class LinkedPositionMessages { + + private static final String RESOURCE_BUNDLE= LinkedPositionMessages.class.getName(); + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private LinkedPositionMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + */ + public static String getFormattedString(String key, Object arg) { + return MessageFormat.format(getString(key), new Object[] { arg }); + } + + + /** + * Gets a string from the resource bundle and formats it with arguments + */ + public static String getFormattedString(String key, Object[] args) { + return MessageFormat.format(getString(key), args); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.properties new file mode 100644 index 00000000000..267939d0cfc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionMessages.properties @@ -0,0 +1,9 @@ +######################################### +# (c) Copyright IBM Corp. 2000, 2001. +# All Rights Reserved. +######################################### + +LinkedPositionUI.error.title=Error in LinkedPositionError + +LinkedPositionManager.error.contains.line.delimiters=String contains line delimiters. +LinkedPositionManager.error.position.collision=Linked position collides with another linked position. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionUI.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionUI.java new file mode 100644 index 00000000000..10f5a180811 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/link/LinkedPositionUI.java @@ -0,0 +1,505 @@ +package org.eclipse.cdt.internal.ui.text.link; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.custom.VerifyKeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.VerifyEvent; +import org.eclipse.swt.events.VerifyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.text.eclipse2.ITextViewerExtension; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.BadPositionCategoryException; +import org.eclipse.jface.text.DefaultPositionUpdater; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPositionUpdater; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + + +/** + * A user interface for LinkedPositionManager, using ITextViewer. + */ +public class LinkedPositionUI implements LinkedPositionListener, + ITextInputListener, ModifyListener, VerifyListener, VerifyKeyListener, PaintListener, IPropertyChangeListener { + + /** + * A listener for notification when the user cancelled the edit operation. + */ + public interface ExitListener { + void exit(boolean accept); + } + + // leave flags + private static final int UNINSTALL= 1; // uninstall linked position manager + private static final int COMMIT= 2; // commit changes + private static final int DOCUMENT_CHANGED= 4; // document has changed + private static final int UPDATE_CARET= 8; // update caret + + private static final String CARET_POSITION= "LinkedPositionUI.caret.position"; + private static final IPositionUpdater fgUpdater= new DefaultPositionUpdater(CARET_POSITION); + private static final IPreferenceStore fgStore= CPlugin.getDefault().getPreferenceStore(); + + private final ITextViewer fViewer; + private final LinkedPositionManager fManager; + private Color fFrameColor; + + private int fFinalCaretOffset= -1; // no final caret offset + + private Position fFramePosition; + private int fCaretOffset; + + private ExitListener fExitListener; + + /** + * Creates a user interface for LinkedPositionManager. + * + * @param viewer the text viewer. + * @param manager the LinkedPositionManager managing a IDocument of the ITextViewer. + */ + public LinkedPositionUI(ITextViewer viewer, LinkedPositionManager manager) { + Assert.isNotNull(viewer); + Assert.isNotNull(manager); + + fViewer= viewer; + fManager= manager; + + fManager.setLinkedPositionListener(this); + + initializeHighlightColor(viewer); + } + + /** + * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(CEditor.LINKED_POSITION_COLOR)) { + initializeHighlightColor(fViewer); + redrawRegion(); + } + } + + private void initializeHighlightColor(ITextViewer viewer) { + + if (fFrameColor != null) + fFrameColor.dispose(); + + StyledText text= viewer.getTextWidget(); + if (text != null) { + Display display= text.getDisplay(); + fFrameColor= createColor(fgStore, CEditor.LINKED_POSITION_COLOR, display); + } + } + + /** + * Creates a color from the information stored in the given preference store. + * Returns null if there is no such information available. + */ + private Color createColor(IPreferenceStore store, String key, Display display) { + + RGB rgb= null; + + if (store.contains(key)) { + + if (store.isDefault(key)) + rgb= PreferenceConverter.getDefaultColor(store, key); + else + rgb= PreferenceConverter.getColor(store, key); + + if (rgb != null) + return new Color(display, rgb); + } + + return null; + } + + /** + * Sets the final position of the caret when the linked mode is exited + * successfully by leaving the last linked position using TAB. + */ + public void setFinalCaretOffset(int offset) { + fFinalCaretOffset= offset; + } + + /** + * Sets a CancelListener which is notified if the linked mode + * is exited unsuccessfully by hitting ESC. + */ + public void setCancelListener(ExitListener listener) { + fExitListener= listener; + } + + /* + * @see LinkedPositionManager.LinkedPositionListener#setCurrentPositions(Position, int) + */ + public void setCurrentPosition(Position position, int caretOffset) { + if (!fFramePosition.equals(position)) { + redrawRegion(); + fFramePosition= position; + } + + fCaretOffset= caretOffset; + } + + /** + * Enters the linked mode. The linked mode can be left by calling + * exit. + * + * @see exit(boolean) + */ + public void enter() { + // track final caret + IDocument document= fViewer.getDocument(); + document.addPositionCategory(CARET_POSITION); + document.addPositionUpdater(fgUpdater); + try { + if (fFinalCaretOffset != -1) + document.addPosition(CARET_POSITION, new Position(fFinalCaretOffset)); + } catch (BadLocationException e) { + openErrorDialog(fViewer.getTextWidget().getShell(), e); + + } catch (BadPositionCategoryException e) { + CPlugin.log(e); + Assert.isTrue(false); + } + + fViewer.addTextInputListener(this); + + ITextViewerExtension extension= (ITextViewerExtension) fViewer; + extension.prependVerifyKeyListener(this); + + StyledText text= fViewer.getTextWidget(); + text.addVerifyListener(this); + text.addModifyListener(this); + text.addPaintListener(this); + text.showSelection(); + + fFramePosition= fManager.getFirstPosition(); + if (fFramePosition == null) + leave(UNINSTALL | COMMIT | UPDATE_CARET); + + fgStore.addPropertyChangeListener(this); + } + + /** + * @see LinkedPositionManager.LinkedPositionListener#exit(boolean) + */ + public void exit(boolean success) { + // no UNINSTALL since manager has already uninstalled itself + leave((success ? COMMIT : 0) | UPDATE_CARET); + } + + /** + * Returns the cursor selection, after having entered the linked mode. + * enter() must be called prior to a call to this method. + */ + public IRegion getSelectedRegion() { + if (fFramePosition == null) + return new Region(fFinalCaretOffset, 0); + else + return new Region(fFramePosition.getOffset(), fFramePosition.getLength()); + } + + private void leave(int flags) { + if ((flags & UNINSTALL) != 0) + fManager.uninstall((flags & COMMIT) != 0); + + fgStore.removePropertyChangeListener(this); + + if (fFrameColor != null) { + fFrameColor.dispose(); + fFrameColor= null; + } + + StyledText text= fViewer.getTextWidget(); + text.removePaintListener(this); + text.removeModifyListener(this); + text.removeVerifyListener(this); + + ITextViewerExtension extension= (ITextViewerExtension) fViewer; + extension.removeVerifyKeyListener(this); + + fViewer.removeTextInputListener(this); + + try { + IRegion region= fViewer.getVisibleRegion(); + IDocument document= fViewer.getDocument(); + + if (((flags & COMMIT) != 0) && + ((flags & DOCUMENT_CHANGED) == 0) && + ((flags & UPDATE_CARET) != 0)) + { + Position[] positions= document.getPositions(CARET_POSITION); + + if ((positions != null) && (positions.length != 0)) { + int offset= positions[0].getOffset() - region.getOffset(); + if ((offset >= 0) && (offset <= region.getLength())) + text.setSelection(offset, offset); + } + } + + document.removePositionUpdater(fgUpdater); + document.removePositionCategory(CARET_POSITION); + + if (fExitListener != null) + fExitListener.exit( + ((flags & COMMIT) != 0) || + ((flags & DOCUMENT_CHANGED) != 0)); + + } catch (BadPositionCategoryException e) { + CPlugin.log(e); + Assert.isTrue(false); + } + + if ((flags & DOCUMENT_CHANGED) == 0) + text.redraw(); + } + + private void next() { + redrawRegion(); + + fFramePosition= fManager.getNextPosition(fFramePosition.getOffset()); + if (fFramePosition == null) { + leave(UNINSTALL | COMMIT | UPDATE_CARET); + } else { + selectRegion(); + redrawRegion(); + } + } + + private void previous() { + redrawRegion(); + + Position position= fManager.getPreviousPosition(fFramePosition.getOffset()); + if (position == null) { + fViewer.getTextWidget().getDisplay().beep(); + } else { + fFramePosition= position; + selectRegion(); + redrawRegion(); + } + } + + /* + * @see VerifyKeyListener#verifyKey(VerifyEvent) + */ + public void verifyKey(VerifyEvent event) { + switch (event.character) { + // [SHIFT-]TAB = hop between edit boxes + case 0x09: + { + Point selection= fViewer.getTextWidget().getSelection(); + IRegion region= fViewer.getVisibleRegion(); + int offset= selection.x + region.getOffset(); + int length= selection.y - selection.x; + + // if tab was treated as a document change, would it exceed variable range? + if (!LinkedPositionManager.includes(fFramePosition, offset, length)) { + leave(UNINSTALL | COMMIT | UPDATE_CARET); + return; + } + } + + if (event.stateMask == SWT.SHIFT) + previous(); + else + next(); + + event.doit= false; + break; + + // ENTER + case 0x0D: + leave(UNINSTALL | COMMIT | UPDATE_CARET); + event.doit= false; + break; + + // ESC + case 0x1B: + leave(UNINSTALL | COMMIT); + event.doit= false; + break; + } + } + + /* + * @see VerifyListener#verifyText(VerifyEvent) + */ + public void verifyText(VerifyEvent event) { + if (!event.doit) + return; + + IRegion region= fViewer.getVisibleRegion(); + + int offset= event.start + region.getOffset(); + int length= event.end - event.start; + + // allow changes only within linked positions when coming through UI + if (!fManager.anyPositionIncludes(offset, length)) + leave(UNINSTALL | COMMIT); + } + + /* + * @see PaintListener#paintControl(PaintEvent) + */ + public void paintControl(PaintEvent event) { + if (fFramePosition == null) + return; + + IRegion region= fViewer.getVisibleRegion(); + + // #6824 + if (!includes(region, fFramePosition)) { + leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED); + return; + } + + int offset= fFramePosition.getOffset() - region.getOffset(); + int length= fFramePosition.getLength(); + + StyledText text= fViewer.getTextWidget(); + + // support for bidi + Point minLocation= getMinimumLocation(text, offset, length); + Point maxLocation= getMaximumLocation(text, offset, length); + + int x1= minLocation.x; + int x2= minLocation.x + maxLocation.x - minLocation.x - 1; + int y= minLocation.y + text.getLineHeight() - 1; + + GC gc= event.gc; + gc.setForeground(fFrameColor); + gc.drawLine(x1, y, x2, y); + } + + private static Point getMinimumLocation(StyledText text, int offset, int length) { + Point minLocation= new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + + for (int i= 0; i <= length; i++) { + Point location= text.getLocationAtOffset(offset + i); + + if (location.x < minLocation.x) + minLocation.x= location.x; + if (location.y < minLocation.y) + minLocation.y= location.y; + } + + return minLocation; + } + + private static Point getMaximumLocation(StyledText text, int offset, int length) { + Point maxLocation= new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + + for (int i= 0; i <= length; i++) { + Point location= text.getLocationAtOffset(offset + i); + + if (location.x > maxLocation.x) + maxLocation.x= location.x; + if (location.y > maxLocation.y) + maxLocation.y= location.y; + } + + return maxLocation; + } + + private void redrawRegion() { + IRegion region= fViewer.getVisibleRegion(); + + if (!includes(region, fFramePosition)) { + leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED); + return; + } + + int offset= fFramePosition.getOffset() - region.getOffset(); + int length= fFramePosition.getLength(); + + fViewer.getTextWidget().redrawRange(offset, length, true); + } + + private void selectRegion() { + IRegion region= fViewer.getVisibleRegion(); + + if (!includes(region, fFramePosition)) { + leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED); + return; + } + + int start= fFramePosition.getOffset() - region.getOffset(); + int end= fFramePosition.getLength() + start; + + fViewer.getTextWidget().setSelection(start, end); + } + + private void updateCaret() { + IRegion region= fViewer.getVisibleRegion(); + + if (!includes(region, fFramePosition)) { + leave(UNINSTALL | COMMIT | DOCUMENT_CHANGED); + return; + } + + int offset= fFramePosition.getOffset() + fCaretOffset - region.getOffset(); + + if ((offset >= 0) && (offset <= region.getLength())) + fViewer.getTextWidget().setCaretOffset(offset); + } + + /* + * @see ModifyListener#modifyText(ModifyEvent) + */ + public void modifyText(ModifyEvent e) { + // reposition caret after StyledText + redrawRegion(); + updateCaret(); + } + + private static void openErrorDialog(Shell shell, Exception e) { + MessageDialog.openError(shell, LinkedPositionMessages.getString("LinkedPositionUI.error.title"), e.getMessage()); //$NON-NLS-1$ + } + + /* + * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument, IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + // 5326: leave linked mode on document change + int flags= UNINSTALL | COMMIT | (oldInput.equals(newInput) ? 0 : DOCUMENT_CHANGED); + leave(flags); + } + + /* + * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + } + + private static boolean includes(IRegion region, Position position) { + return + position.getOffset() >= region.getOffset() && + position.getOffset() + position.getLength() <= region.getOffset() + region.getLength(); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateContentProvider.java new file mode 100644 index 00000000000..0440dce8286 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateContentProvider.java @@ -0,0 +1,39 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.TemplateSet; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + + +public class TemplateContentProvider implements IStructuredContentProvider { + + private TemplateSet fTemplateSet; + + /** + * @see IStructuredContentProvider#getElements(Object) + */ + public Object[] getElements(Object input) { + return fTemplateSet.getTemplates(); + } + + /** + * @see IContentProvider#inputChanged(Viewer, Object, Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + fTemplateSet= (TemplateSet) newInput; + } + + /** + * @see IContentProvider#dispose() + */ + public void dispose() { + fTemplateSet= null; + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateEngine.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateEngine.java new file mode 100644 index 00000000000..e3e7a4ae012 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateEngine.java @@ -0,0 +1,91 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.corext.template.Templates; +import org.eclipse.cdt.internal.corext.template.c.CompilationUnitContext; +import org.eclipse.cdt.internal.corext.template.c.CompilationUnitContextType; +import org.eclipse.cdt.internal.corext.template.c.ICompilationUnit; +import org.eclipse.cdt.internal.ui.text.ICCompletionProposal; +import org.eclipse.cdt.internal.ui.text.link.LinkedPositionManager; +import java.util.ArrayList; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.util.Assert; +import org.eclipse.jface.viewers.ITableLabelProvider; + +public class TemplateEngine { + + private ContextType fContextType; + private ITableLabelProvider fLabelProvider= new TemplateLabelProvider(); + + private ArrayList fProposals= new ArrayList(); + + /** + * Creates the template engine for a particular context type. + * See TemplateContext for supported context types. + */ + public TemplateEngine(ContextType contextType) { + Assert.isNotNull(contextType); + fContextType= contextType; + } + + /** + * Empties the collector. + * + * @param viewer the text viewer + * @param unit the compilation unit (may be null) + */ + public void reset() { + fProposals.clear(); + } + + /** + * Returns the array of matching templates. + */ + public ICCompletionProposal[] getResults() { + return (ICCompletionProposal[]) fProposals.toArray(new ICCompletionProposal[fProposals.size()]); + } + + /** + * Inspects the context of the compilation unit around completionPosition + * and feeds the collector with proposals. + * @param viewer the text viewer + * @param completionPosition the context position in the document of the text viewer + * @param compilationUnit the compilation unit (may be null) + */ + public void complete(ITextViewer viewer, int completionPosition, ICompilationUnit compilationUnit) + //throws JavaModelException + { + IDocument document= viewer.getDocument(); + + // prohibit recursion + if (LinkedPositionManager.hasActiveManager(document)) + return; + + if (!(fContextType instanceof CompilationUnitContextType)) + return; + + ((CompilationUnitContextType) fContextType).setContextParameters(document.get(), completionPosition, compilationUnit); + CompilationUnitContext context= (CompilationUnitContext) fContextType.createContext(); + int start= context.getStart(); + int end= context.getEnd(); + IRegion region= new Region(start, end - start); + + Template[] templates= Templates.getInstance().getTemplates(); + for (int i= 0; i != templates.length; i++) + if (context.canEvaluate(templates[i])) + fProposals.add(new TemplateProposal(templates[i], context, region, viewer, fLabelProvider.getColumnImage(templates[i], 0))); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateLabelProvider.java new file mode 100644 index 00000000000..a6860e7f59a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateLabelProvider.java @@ -0,0 +1,72 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.graphics.Image; + +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITableLabelProvider; + + +public class TemplateLabelProvider implements ITableLabelProvider { + + /* + * @see ITableLabelProvider#getColumnImage(Object, int) + */ + public Image getColumnImage(Object element, int columnIndex) { + if (columnIndex != 0) + return null; + + return CPluginImages.get(CPluginImages.IMG_OBJS_TEMPLATE); + } + + /* + * @see ITableLabelProvider#getColumnText(Object, int) + */ + public String getColumnText(Object element, int columnIndex) { + Template template = (Template) element; + + switch (columnIndex) { + case 0: + return template.getName(); + case 1: + return template.getContextTypeName(); + case 2: + return template.getDescription(); + default: + return null; + } + } + + /* + * @see IBaseLabelProvider#addListener(ILabelProviderListener) + */ + public void addListener(ILabelProviderListener listener) { + } + + /* + * @see IBaseLabelProvider#dispose() + */ + public void dispose() { + } + + /* + * @see IBaseLabelProvider#isLabelProperty(Object, String) + */ + public boolean isLabelProperty(Object element, String property) { + return false; + } + + /* + * @see IBaseLabelProvider#removeListener(ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener listener) { + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateProposal.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateProposal.java new file mode 100644 index 00000000000..f3bc98a97ad --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateProposal.java @@ -0,0 +1,225 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.corext.template.Template; +import org.eclipse.cdt.internal.corext.template.TemplateBuffer; +import org.eclipse.cdt.internal.corext.template.TemplateContext; +import org.eclipse.cdt.internal.corext.template.TemplateMessages; +import org.eclipse.cdt.internal.corext.template.TemplatePosition; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.text.ICCompletionProposal; +import org.eclipse.cdt.internal.ui.text.link.LinkedPositionManager; +import org.eclipse.cdt.internal.ui.text.link.LinkedPositionUI; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.util.Assert; + +/** + * A template proposal. + */ +public class TemplateProposal implements ICCompletionProposal { + + private final Template fTemplate; + private final TemplateContext fContext; + private final ITextViewer fViewer; + private final Image fImage; + private final IRegion fRegion; + + private TemplateBuffer fTemplateBuffer; + private String fOldText; + private IRegion fSelectedRegion; // initialized by apply() + + /** + * Creates a template proposal with a template and its context. + * @param template the template + * @param context the context in which the template was requested. + * @param image the icon of the proposal. + */ + public TemplateProposal(Template template, TemplateContext context, IRegion region, ITextViewer viewer, Image image) { + Assert.isNotNull(template); + Assert.isNotNull(context); + Assert.isNotNull(region); + Assert.isNotNull(viewer); + + fTemplate= template; + fContext= context; + fViewer= viewer; + fImage= image; + fRegion= region; + } + + /** + * @see ICompletionProposal#apply(IDocument) + */ + public void apply(IDocument document) { + try { + if (fTemplateBuffer == null) + fTemplateBuffer= fContext.evaluate(fTemplate); + + int start= fRegion.getOffset(); + int end= fRegion.getOffset() + fRegion.getLength(); + + // insert template string + String templateString= fTemplateBuffer.getString(); + document.replace(start, end - start, templateString); + + // translate positions + LinkedPositionManager manager= new LinkedPositionManager(document); + TemplatePosition[] variables= fTemplateBuffer.getVariables(); + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + if (variable.isResolved()) + continue; + + int[] offsets= variable.getOffsets(); + int length= variable.getLength(); + + for (int j= 0; j != offsets.length; j++) + manager.addPosition(offsets[j] + start, length); + } + + LinkedPositionUI editor= new LinkedPositionUI(fViewer, manager); + editor.setFinalCaretOffset(getCaretOffset(fTemplateBuffer) + start); + editor.enter(); + + fSelectedRegion= editor.getSelectedRegion(); + + } catch (BadLocationException e) { + CPlugin.log(e); + openErrorDialog(e); + + } catch (CoreException e) { + CPlugin.log(e); + openErrorDialog(e); + } + } + + private static int getCaretOffset(TemplateBuffer buffer) { + TemplatePosition[] variables= buffer.getVariables(); + for (int i= 0; i != variables.length; i++) { + TemplatePosition variable= variables[i]; + + if (variable.getName().equals("cursor")) + return variable.getOffsets()[0]; + } + + return buffer.getString().length(); + } + + /** + * @see ICompletionProposal#getSelection(IDocument) + */ + public Point getSelection(IDocument document) { + return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength()); + } + + /** + * @see ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + try { + if (fTemplateBuffer == null) + fTemplateBuffer= fContext.evaluate(fTemplate); + + return textToHTML(fTemplateBuffer.getString()); + + } catch (CoreException e) { + CPlugin.log(e); + openErrorDialog(e); + + return null; + } + } + + /** + * @see ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return fTemplate.getName() + TemplateMessages.getString("TemplateProposal.delimiter") + fTemplate.getDescription(); // $NON-NLS-1$ //$NON-NLS-1$ + } + + /** + * @see ICompletionProposal#getImage() + */ + public Image getImage() { + return fImage; + } + + /** + * @see ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return null; + } + + private static String textToHTML(String string) { + StringBuffer buffer= new StringBuffer(string.length()); + buffer.append("
"); //$NON-NLS-1$
+	
+		for (int i= 0; i != string.length(); i++) {
+			char ch= string.charAt(i);
+			
+			switch (ch) {
+				case '&':
+					buffer.append("&"); //$NON-NLS-1$
+					break;
+					
+				case '<':
+					buffer.append("<"); //$NON-NLS-1$
+					break;
+
+				case '>':
+					buffer.append(">"); //$NON-NLS-1$
+					break;
+
+				case '\t':
+					buffer.append("    "); //$NON-NLS-1$
+					break;
+
+				case '\n':
+					buffer.append("
"); //$NON-NLS-1$ + break; + + default: + buffer.append(ch); + break; + } + } + + buffer.append("
"); //$NON-NLS-1$ + return buffer.toString(); + } + + private void openErrorDialog(BadLocationException e) { + Shell shell= fViewer.getTextWidget().getShell(); + MessageDialog.openError(shell, TemplateMessages.getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$ + } + + private void openErrorDialog(CoreException e) { + Shell shell= fViewer.getTextWidget().getShell(); + MessageDialog.openError(shell, TemplateMessages.getString("TemplateEvaluator.error.title"), e.getMessage()); //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see IJavaCompletionProposal#getRelevance() + */ + public int getRelevance() { + return 90; + } + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java new file mode 100644 index 00000000000..e583dcd8fd8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProcessor.java @@ -0,0 +1,135 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + + +import org.eclipse.cdt.internal.corext.template.ContextType; +import org.eclipse.cdt.internal.corext.template.TemplateVariable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + + +public class TemplateVariableProcessor implements IContentAssistProcessor { + + private static Comparator fgTemplateVariableProposalComparator= new Comparator() { + public int compare(Object arg0, Object arg1) { + TemplateVariableProposal proposal0= (TemplateVariableProposal) arg0; + TemplateVariableProposal proposal1= (TemplateVariableProposal) arg1; + + return proposal0.getDisplayString().compareTo(proposal1.getDisplayString()); + } + + public boolean equals(Object arg0) { + return false; + } + }; + + + /** the context type */ + private ContextType fContextType; + + /** + * Sets the context type. + */ + public void setContextType(ContextType contextType) { + fContextType= contextType; + } + + /* + * @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int) + */ + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { + + if (fContextType == null) + return null; + + List proposals= new ArrayList(); + + String text= viewer.getDocument().get(); + int start= getStart(text, documentOffset); + int end= documentOffset; + + String string= text.substring(start, end); + String prefix= (string.length() >= 2) + ? string.substring(2) + : null; + + int offset= start; + int length= end - start; + + for (Iterator iterator= fContextType.variableIterator(); iterator.hasNext(); ) { + TemplateVariable variable= (TemplateVariable) iterator.next(); + + if (prefix == null || variable.getName().startsWith(prefix)) + proposals.add(new TemplateVariableProposal(variable, offset, length, viewer)); + } + + Collections.sort(proposals, fgTemplateVariableProposalComparator); + return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]); + } + + /* Guesses the start position of the completion */ + private int getStart(String string, int end) { + int start= end; + + if (start >= 1 && string.charAt(start - 1) == '$') + return start - 1; + + while ((start != 0) && Character.isUnicodeIdentifierPart(string.charAt(start - 1))) + start--; + + if (start >= 2 && string.charAt(start - 1) == '{' && string.charAt(start - 2) == '$') + return start - 2; + + return end; + } + + /* + * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int) + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { + return null; + } + + /* + * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return new char[] {'$'}; + } + + /* + * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters() + */ + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + /* + * @see IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return null; + } + + /* + * @see IContentAssistProcessor#getContextInformationValidator() + */ + public IContextInformationValidator getContextInformationValidator() { + return null; + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java new file mode 100644 index 00000000000..b3a2a904d4f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/template/TemplateVariableProposal.java @@ -0,0 +1,103 @@ +package org.eclipse.cdt.internal.ui.text.template; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Shell; + +import org.eclipse.cdt.internal.corext.template.TemplateMessages; +import org.eclipse.cdt.internal.corext.template.TemplateVariable; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; + + +/** + * A proposal for insertion of template variables. + */ +public class TemplateVariableProposal implements ICompletionProposal { + + private TemplateVariable fVariable; + private int fOffset; + private int fLength; + private ITextViewer fViewer; + + private Point fSelection; + + /** + * Creates a template variable proposal. + * + * @param variable the template variable + * @param offset the offset to replace + * @param length the length to replace + * @param viewer the viewer + */ + public TemplateVariableProposal(TemplateVariable variable, int offset, int length, ITextViewer viewer) { + fVariable= variable; + fOffset= offset; + fLength= length; + fViewer= viewer; + } + + /* + * @see ICompletionProposal#apply(IDocument) + */ + public void apply(IDocument document) { + + try { + String variable= fVariable.getName().equals("dollar") ? "$$" : "${" + fVariable.getName() + '}'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + document.replace(fOffset, fLength, variable); + fSelection= new Point(fOffset + variable.length(), 0); + + } catch (BadLocationException e) { + CPlugin.log(e); + + Shell shell= fViewer.getTextWidget().getShell(); + MessageDialog.openError(shell, TemplateMessages.getString("TemplateVariableProposal.error.title"), e.getMessage()); //$NON-NLS-1$ + } + } + + /* + * @see ICompletionProposal#getSelection(IDocument) + */ + public Point getSelection(IDocument document) { + return fSelection; + } + + /* + * @see ICompletionProposal#getAdditionalProposalInfo() + */ + public String getAdditionalProposalInfo() { + return null; + } + + /* + * @see ICompletionProposal#getDisplayString() + */ + public String getDisplayString() { + return fVariable.getName() + " - " + fVariable.getDescription(); //$NON-NLS-1$ + } + + /* + * @see ICompletionProposal#getImage() + */ + public Image getImage() { + return null; + } + + /* + * @see ICompletionProposal#getContextInformation() + */ + public IContextInformation getContextInformation() { + return null; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CColorManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CColorManager.java new file mode 100644 index 00000000000..63566d70832 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CColorManager.java @@ -0,0 +1,106 @@ +package org.eclipse.cdt.internal.ui.text.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.ui.text.IColorManager; +import org.eclipse.cdt.internal.ui.text.IColorManagerExtension; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +/** + * Java color manager. + */ +public class CColorManager implements IColorManager, IColorManagerExtension { + + protected Map fKeyTable= new HashMap(10); + protected Map fDisplayTable= new HashMap(2); + + + public CColorManager() { + } + + private void dispose(Display display) { + Map colorTable= (Map) fDisplayTable.get(display); + if (colorTable != null) { + Iterator e= colorTable.values().iterator(); + while (e.hasNext()) + ((Color) e.next()).dispose(); + } + } + + /* + * @see IColorManager#getColor(RGB) + */ + public Color getColor(RGB rgb) { + + if (rgb == null) + return null; + + final Display display= Display.getCurrent(); + Map colorTable= (Map) fDisplayTable.get(display); + if (colorTable == null) { + colorTable= new HashMap(10); + fDisplayTable.put(display, colorTable); + display.disposeExec(new Runnable() { + public void run() { + dispose(display); + } + }); + } + + Color color= (Color) colorTable.get(rgb); + if (color == null) { + color= new Color(Display.getCurrent(), rgb); + colorTable.put(rgb, color); + } + + return color; + } + + /* + * @see IColorManager#dispose + */ + public void dispose() { + // nothing to dispose + } + + /* + * @see IColorManager#getColor(String) + */ + public Color getColor(String key) { + + if (key == null) + return null; + + RGB rgb= (RGB) fKeyTable.get(key); + return getColor(rgb); + } + + /* + * @see IColorManagerExtension#bindColor(String, RGB) + */ + public void bindColor(String key, RGB rgb) { + Object value= fKeyTable.get(key); + if (value != null) + throw new UnsupportedOperationException(); + + fKeyTable.put(key, rgb); + } + + /* + * @see IColorManagerExtension#unbindColor(String) + */ + public void unbindColor(String key) { + fKeyTable.remove(key); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java new file mode 100644 index 00000000000..99aff354b02 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWhitespaceDetector.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.internal.ui.text.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.rules.IWhitespaceDetector; + + +/** + * A C aware white space detector. + */ +public class CWhitespaceDetector implements IWhitespaceDetector { + + /** + * @see IWhitespaceDetector#isWhitespace + */ + public boolean isWhitespace(char c) { + return Character.isWhitespace(c); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java new file mode 100644 index 00000000000..c104926d8f5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/util/CWordDetector.java @@ -0,0 +1,30 @@ +package org.eclipse.cdt.internal.ui.text.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.rules.IWordDetector; + + +/** + * A C aware word detector. + */ +public class CWordDetector implements IWordDetector { + + + /** + * @see IWordDetector#isWordIdentifierStart + */ + public boolean isWordStart(char c) { + return Character.isJavaIdentifierStart(c); + } + + /** + * @see IWordDetector#isWordIdentifierPart + */ + public boolean isWordPart(char c) { + return Character.isJavaIdentifierPart(c); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CoreUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CoreUtility.java new file mode 100644 index 00000000000..31ffae7594c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/CoreUtility.java @@ -0,0 +1,43 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + + +public class CoreUtility { + + /** + * Adds a nauture to a project + */ + public static void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException { + IProjectDescription description = proj.getDescription(); + String[] prevNatures= description.getNatureIds(); + String[] newNatures= new String[prevNatures.length + 1]; + System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); + newNatures[prevNatures.length]= natureId; + description.setNatureIds(newNatures); + proj.setDescription(description, monitor); + } + /** + * Creates a folder and all parent folders if not existing + * Project must exist + */ + public static void createFolder(IFolder folder, boolean force, boolean local, IProgressMonitor monitor) throws CoreException { + if (!folder.exists()) { + IContainer parent= folder.getParent(); + if (parent instanceof IFolder) { + createFolder((IFolder)parent, force, local, monitor); + } + folder.create(force, local, monitor); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/DeleteTaskAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/DeleteTaskAction.java new file mode 100644 index 00000000000..558e5c3a2ba --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/DeleteTaskAction.java @@ -0,0 +1,86 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.actions.ActionDelegate; + +import org.eclipse.cdt.core.model.ICModelMarker; + +public class DeleteTaskAction extends ActionDelegate implements IObjectActionDelegate +{ + private IStructuredSelection selection; + + /** + * @see ActionDelegate#run(IAction) + */ + public void run(IAction action) { + // Add your code here to perform the action + if (selection != null) { + if (selection.isEmpty()) { + return; + } + try { + List list = ((IStructuredSelection) selection).toList(); + List listMarkers = new ArrayList(); + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + IMarker marker = (IMarker)iterator.next(); + if (marker.isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER) + || marker.isSubtypeOf(ICModelMarker.C_MODEL_MARKER_VARIABLE)) { + listMarkers.add(marker); + } + } + // Bail out early + if (listMarkers.isEmpty()) { + return; + } + IMarker[] markers = new IMarker[listMarkers.size()]; + listMarkers.toArray(markers); + // be sure to only invoke one workspace operation + ResourcesPlugin.getWorkspace().deleteMarkers(markers); + selection = null; + } catch (CoreException e) { + } + } + } + + /** + * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + + public void selectionChanged(IAction action, ISelection selection) { + boolean enable = false; + if (selection instanceof IStructuredSelection) { + Object object = ((IStructuredSelection) selection).getFirstElement(); + if (object instanceof IMarker) { + try { + IMarker marker = (IMarker) object; + if (marker.isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER) + || marker.isSubtypeOf(ICModelMarker.C_MODEL_MARKER_VARIABLE)) { + enable = true; + } + this.selection = (IStructuredSelection)selection; + action.setEnabled(enable); + } catch (CoreException e) { + } + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java new file mode 100644 index 00000000000..5dab79362c5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/EditorUtility.java @@ -0,0 +1,153 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.core.FileStorage; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.utils.spawner.ProcessFactory; + +public class EditorUtility { + + private EditorUtility () { + } + + public static IEditorPart openInEditor (IFile file) throws PartInitException { + IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + if (window != null) { + IWorkbenchPage p= window.getActivePage(); + if (p != null) { + return p.openEditor(file); + } + } + return null; + } + + public static IEditorPart openInEditor (ICElement element) throws PartInitException { + IResource res = null; + try { + res = element.getUnderlyingResource(); + } catch (CModelException e) { + } + + // Treat binary differently + if (element instanceof IBinary) { + IStorage store = getStorage((IBinary)element); + if (store != null) { + return openInEditor(store, element.getElementName()); + } + } + + if (res != null && res instanceof IFile) { + IEditorPart editor = openInEditor((IFile)res); + if (editor instanceof CEditor) { + CEditor e = (CEditor)editor; + StructuredSelection selection = new StructuredSelection(element); + e.selectionChanged (new SelectionChangedEvent (e.getOutlinePage (), selection)); + } + return editor; + } + return null; + } + + public static IEditorPart openInEditor (IPath path) throws PartInitException { + IFile f = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path); + if (f == null) { + IStorage s = new FileStorage(path); + return openInEditor(s, path.lastSegment()); + } + return openInEditor(f); + } + + public static IEditorPart openInEditor (IStorage store, String name) throws PartInitException { + IEditorInput ei = new ExternalEditorInput(store); + IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + if (window != null) { + IWorkbenchPage p = window.getActivePage(); + if (p != null) { + return p.openEditor(ei, getEditorID(name)); + } + } + return null; + } + + public static String getEditorID(String name) { + IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); + if (registry != null) { + IEditorDescriptor descriptor = registry.getDefaultEditor(name); + if (descriptor != null) { + return descriptor.getId(); + } else { + return registry.getDefaultEditor().getId(); + } + } + return null; + } + + /** + * Selects a C Element in an editor + */ + public static void revealInEditor(IEditorPart part, ICElement element) { + if (element != null && part instanceof CEditor) { + //((CEditor) part).setSelection(element); + } + } + + public static IStorage getStorage(IBinary bin) { + IStorage store = null; + Process objdump = null; + IPath path; + IFile file = bin.getFile(); + if (file == null) + return store; + path = file.getLocation(); + try { + String[] args = new String[] {"objdump", "-CxS", path.toOSString()}; + objdump = ProcessFactory.getFactory().exec(args); + StringBuffer buffer = new StringBuffer(); + BufferedReader stdout = + new BufferedReader(new InputStreamReader(objdump.getInputStream())); + char[] buf = new char[128]; + while (stdout.read(buf, 0, buf.length) != -1) { + buffer.append(buf); + } + store = new FileStorage(new ByteArrayInputStream(buffer.toString().getBytes()), path); + } catch (SecurityException e) { + } catch (IndexOutOfBoundsException e) { + } catch (NullPointerException e) { + } catch (IOException e) { + } finally { + if (objdump != null) { + objdump.destroy(); + } + } + return store; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ExternalEditorInput.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ExternalEditorInput.java new file mode 100644 index 00000000000..34ba1e29312 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ExternalEditorInput.java @@ -0,0 +1,104 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.resource.ImageDescriptor; + +import org.eclipse.core.resources.IStorage; + +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.IPersistableElement; +import org.eclipse.ui.IStorageEditorInput; +import org.eclipse.ui.PlatformUI; + + +/** + * An EditorInput for a JarEntryFile. + */ +public class ExternalEditorInput implements IStorageEditorInput { + + IStorage externalFile; + + /* + */ + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof ExternalEditorInput)) + return false; + ExternalEditorInput other = (ExternalEditorInput)obj; + return externalFile.equals(other.externalFile); + } + + /* + * @see IEditorInput#exists() + */ + public boolean exists() { + // External file ca not be deleted + return true; + } + + /* + * @see IAdaptable#getAdapter(Class) + */ + public Object getAdapter(Class adapter) { + return null; + } + + /* + * @see IEditorInput#getContentType() + */ + public String getContentType() { + return externalFile.getFullPath().getFileExtension(); + } + + /* + * @see IEditorInput#getFullPath() + */ + public String getFullPath() { + return externalFile.getFullPath().toString(); + } + + /* + * @see IEditorInput#getImageDescriptor() + */ + public ImageDescriptor getImageDescriptor() { + IEditorRegistry registry= PlatformUI.getWorkbench().getEditorRegistry(); + return registry.getImageDescriptor(externalFile.getFullPath().getFileExtension()); + } + + /* + * @see IEditorInput#getName() + */ + public String getName() { + return externalFile.getName(); + } + + /* + * @see IEditorInput#getPersistable() + */ + public IPersistableElement getPersistable() { + return null; + } + + /* + * see IStorageEditorInput#getStorage() + */ + public IStorage getStorage() { + return externalFile; + } + + /* + * @see IEditorInput#getToolTipText() + */ + public String getToolTipText() { + return externalFile.getFullPath().toString(); + } + + public ExternalEditorInput(IStorage exFile) { + externalFile = exFile; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/IProblemChangedListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/IProblemChangedListener.java new file mode 100644 index 00000000000..354e19e9c19 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/IProblemChangedListener.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Set; + +/** + * Can be added to a ProblemMarkerManager to get notified about error + * marker changes. Used to update error ticks. + */ +public interface IProblemChangedListener { + + /** + * @param changedElements A set of type IPath that + * describe the resources that had an error marker change. + */ + void problemsChanged(Set changedElements); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ImageDescriptorRegistry.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ImageDescriptorRegistry.java new file mode 100644 index 00000000000..5d65893821d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ImageDescriptorRegistry.java @@ -0,0 +1,87 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.Assert; + +/** + * A registry that maps ImageDescriptors to Image. + */ +public class ImageDescriptorRegistry { + + private HashMap fRegistry= new HashMap(10); + private Display fDisplay; + + /** + * Creates a new image descriptor registry for the current or default display, + * respectively. + */ + public ImageDescriptorRegistry() { + this(SWTUtil.getStandardDisplay()); + } + + /** + * Creates a new image descriptor registry for the given display. All images + * managed by this registry will be disposed when the display gets disposed. + * + * @param diaplay the display the images managed by this registry are allocated for + */ + public ImageDescriptorRegistry(Display display) { + fDisplay= display; + Assert.isNotNull(fDisplay); + hookDisplay(); + } + + /** + * Returns the image assiciated with the given image descriptor. + * + * @param descriptor the image descriptor for which the registry manages an image + * @return the image associated with the image descriptor or null + * if the image descriptor can't create the requested image. + */ + public Image get(ImageDescriptor descriptor) { + if (descriptor == null) + descriptor= ImageDescriptor.getMissingImageDescriptor(); + + Image result= (Image)fRegistry.get(descriptor); + if (result != null) + return result; + + Assert.isTrue(fDisplay == SWTUtil.getStandardDisplay(), "Allocating image for wrong display."); //$NON-NLS-1$ + result= descriptor.createImage(); + if (result != null) + fRegistry.put(descriptor, result); + return result; + } + + /** + * Disposes all images managed by this registry. + */ + public void dispose() { + for (Iterator iter= fRegistry.values().iterator(); iter.hasNext(); ) { + Image image= (Image)iter.next(); + image.dispose(); + } + fRegistry.clear(); + } + + private void hookDisplay() { + fDisplay.disposeExec(new Runnable() { + public void run() { + dispose(); + } + }); + } +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemItemMapper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemItemMapper.java new file mode 100644 index 00000000000..94e70d7c92f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemItemMapper.java @@ -0,0 +1,195 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Item; + +import org.eclipse.jface.viewers.ILabelProvider; + + +/** + * Helper class for updating error markers. + * Items are mapped to paths of their underlying resources. + * Method problemsChanged updates all items that are affected from the changed + * elements. + */ +public class ProblemItemMapper { + + private static final int NUMBER_LIST_REUSE= 10; + + // map from path to item + private HashMap fPathToItem; + private Stack fReuseLists; + + public ProblemItemMapper() { + fPathToItem= new HashMap(); + fReuseLists= new Stack(); + } + + /** + * Updates the icons of all mapped elements containing to the changed elements. + * Must be called from the UI thread. + */ + public void problemsChanged(Collection changedPaths, ILabelProvider lprovider) { + // iterate over the smaller set/map + if (changedPaths.size() <= fPathToItem.size()) { + iterateChanges(changedPaths, lprovider); + } else { + iterateItems(changedPaths, lprovider); + } + } + + private void iterateChanges(Collection changedPaths, ILabelProvider lprovider) { + Iterator elements= changedPaths.iterator(); + while (elements.hasNext()) { + IPath curr= (IPath) elements.next(); + Object obj= fPathToItem.get(curr); + if (obj == null) { + // not mapped + } else if (obj instanceof Item) { + refreshIcon(lprovider, (Item)obj); + } else { // List of Items + List list= (List) obj; + for (int i= 0; i < list.size(); i++) { + refreshIcon(lprovider, (Item) list.get(i)); + } + } + } + } + + private void iterateItems(Collection changedPaths, ILabelProvider lprovider) { + Iterator keys= fPathToItem.keySet().iterator(); + while (keys.hasNext()) { + IPath curr= (IPath) keys.next(); + if (changedPaths.contains(curr)) { + Object obj= fPathToItem.get(curr); + if (obj instanceof Item) { + refreshIcon(lprovider, (Item)obj); + } else { // List of Items + List list= (List) obj; + for (int i= 0; i < list.size(); i++) { + refreshIcon(lprovider, (Item) list.get(i)); + } + } + } + } + } + + private void refreshIcon(ILabelProvider lprovider, Item item) { + if (!item.isDisposed()) { // defensive code + Object data= item.getData(); + if (data instanceof ICElement && !((ICElement)data).exists()) { + // @@@ not yet return; + } + Image old= item.getImage(); + Image image= lprovider.getImage(data); + if (image != null && image != old) { + item.setImage(image); + } + } + } + + /** + * Adds a new item to the map. + * @param element Element to map + * @param item The item used for the element + */ + public void addToMap(Object element, Item item) { + IPath path= getCorrespondingPath(element); + if (path != null) { + Object existingMapping= fPathToItem.get(path); + if (existingMapping == null) { + fPathToItem.put(path, item); + } else if (existingMapping instanceof Item) { + if (existingMapping != item) { + List list= newList(); + list.add(existingMapping); + list.add(item); + fPathToItem.put(path, list); + } + } else { // List + List list= (List)existingMapping; + if (!list.contains(item)) { + list.add(item); + } + } + } + } + + /** + * Removes an element from the map. + */ + public void removeFromMap(Object element, Item item) { + IPath path= getCorrespondingPath(element); + if (path != null) { + Object existingMapping= fPathToItem.get(path); + if (existingMapping == null) { + return; + } else if (existingMapping instanceof Item) { + fPathToItem.remove(path); + } else { // List + List list= (List) existingMapping; + list.remove(item); + if (list.isEmpty()) { + fPathToItem.remove(list); + releaseList(list); + } + } + } + } + + private List newList() { + if (!fReuseLists.isEmpty()) { + return (List) fReuseLists.pop(); + } + return new ArrayList(2); + } + + private void releaseList(List list) { + if (fReuseLists.size() < NUMBER_LIST_REUSE) { + fReuseLists.push(list); + } + } + + /** + * Clears the map. + */ + public void clearMap() { + fPathToItem.clear(); + } + + /** + * Method that decides which elements can have error markers + * Returns null if an element can not have error markers. + */ + private static IPath getCorrespondingPath(Object element) { + if (element instanceof ICElement) { + ICElement elem= (ICElement) element; + //if (!elem.isReadOnly()) { // only modifieable elements can get error ticks + return elem.getPath(); + //} + //return null; + } else if (element instanceof IResource) { + return ((IResource)element).getFullPath(); + } + return null; + } + +} + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemMarkerManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemMarkerManager.java new file mode 100644 index 00000000000..67c9c442fab --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemMarkerManager.java @@ -0,0 +1,148 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IMarkerDelta; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.jface.util.ListenerList; + + +/** + * Listens to resource deltas and filters for marker changes of type IMarker.PROBLEM + * Viewers showing error ticks should register as listener to + * this type. + */ +public class ProblemMarkerManager implements IResourceChangeListener { + + /** + * Visitors used to filter the element delta changes + */ + private static class ProjectErrorVisitor implements IResourceDeltaVisitor { + + private HashSet fChangedElements; + + public ProjectErrorVisitor(HashSet changedElements) { + fChangedElements= changedElements; + } + + public boolean visit(IResourceDelta delta) throws CoreException { + IResource res= delta.getResource(); + if (res instanceof IProject && delta.getKind() == IResourceDelta.CHANGED) { + try { + IProject project= (IProject) res; + if (!project.isAccessible() || !project.hasNature(CProjectNature.C_NATURE_ID)) { + // only track open C projects + return false; + } + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + return false; + } + } + checkInvalidate(delta, res.getFullPath()); + return true; + } + + private void checkInvalidate(IResourceDelta delta, IPath path) { + int kind= delta.getKind(); + if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.ADDED || (kind == IResourceDelta.CHANGED && isErrorDelta(delta))) { + // invalidate the path and all parent paths + while (!path.isEmpty() && !path.isRoot() && !fChangedElements.contains(path)) { + fChangedElements.add(path); + path= path.removeLastSegments(1); + } + } + } + + private boolean isErrorDelta(IResourceDelta delta) { + if ((delta.getFlags() & IResourceDelta.MARKERS) != 0) { + IMarkerDelta[] markerDeltas= delta.getMarkerDeltas(); + for (int i= 0; i < markerDeltas.length; i++) { + if (markerDeltas[i].isSubtypeOf(ICModelMarker.C_MODEL_PROBLEM_MARKER)) { + int kind= markerDeltas[i].getKind(); + if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) + return true; + int severity= markerDeltas[i].getAttribute(IMarker.SEVERITY, -1); + int newSeverity= markerDeltas[i].getMarker().getAttribute(IMarker.SEVERITY, -1); + if (newSeverity != severity) + return true; + } + } + } + return false; + } + } + + private ListenerList fListeners; + + + public ProblemMarkerManager() { + fListeners= new ListenerList(5); + } + + /* + * @see IResourceChangeListener#resourceChanged + */ + public void resourceChanged(IResourceChangeEvent event) { + HashSet changedElements= new HashSet(); + + try { + IResourceDelta delta= event.getDelta(); + if (delta != null) + delta.accept(new ProjectErrorVisitor(changedElements)); + } catch (CoreException e) { + CPlugin.log(e.getStatus()); + } + + if (changedElements.size() > 0) { + fireChanges(changedElements); + } + } + + /** + * Adds a listener for problem marker changes. + */ + public void addListener(IProblemChangedListener listener) { + if (fListeners.isEmpty()) { + CPlugin.getWorkspace().addResourceChangeListener(this); + } + fListeners.add(listener); + } + + /** + * Removes a IProblemChangedListener. + */ + public void removeListener(IProblemChangedListener listener) { + fListeners.remove(listener); + if (fListeners.isEmpty()) { + CPlugin.getWorkspace().removeResourceChangeListener(this); + } + } + + private void fireChanges(Set changes) { + Object[] listeners= fListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) { + IProblemChangedListener curr= (IProblemChangedListener) listeners[i]; + curr.problemsChanged(changes); + } + } + } + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemTreeViewer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemTreeViewer.java new file mode 100644 index 00000000000..ac8fc8a4c6e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/ProblemTreeViewer.java @@ -0,0 +1,137 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2002. + * All Rights Reserved. + */ + +import java.util.Set; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.Widget; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.LabelProviderChangedEvent; +import org.eclipse.jface.viewers.TreeViewer; + + +/** + * Extends a TreeViewer to allow more performance when showing error ticks. + * A ProblemItemMapper is contained that maps all items in + * the tree to underlying resource + */ +public class ProblemTreeViewer extends TreeViewer implements IProblemChangedListener { + + private ProblemItemMapper fProblemItemMapper; + + /* + * @see TreeViewer#TreeViewer(Composite) + */ + public ProblemTreeViewer(Composite parent) { + super(parent); + initMapper(); + } + + /* + * @see TreeViewer#TreeViewer(Composite, int) + */ + public ProblemTreeViewer(Composite parent, int style) { + super(parent, style); + initMapper(); + } + + /* + * @see TreeViewer#TreeViewer(Tree) + */ + public ProblemTreeViewer(Tree tree) { + super(tree); + initMapper(); + } + + private void initMapper() { + fProblemItemMapper= new ProblemItemMapper(); + } + + + /* + * @see IProblemChangedListener#problemsChanged + */ + public void problemsChanged(final Set changed) { + Control control= getControl(); + if (control != null && !control.isDisposed()) { + control.getDisplay().asyncExec(new Runnable() { + public void run() { + fProblemItemMapper.problemsChanged(changed, (ILabelProvider)getLabelProvider()); + } + }); + } + } + + /* + * @see StructuredViewer#mapElement(Object, Widget) + */ + protected void mapElement(Object element, Widget item) { + super.mapElement(element, item); + if (item instanceof Item) { + fProblemItemMapper.addToMap(element, (Item) item); + } + } + + /* + * @see StructuredViewer#unmapElement(Object, Widget) + */ + protected void unmapElement(Object element, Widget item) { + if (item instanceof Item) { + fProblemItemMapper.removeFromMap(element, (Item) item); + } + super.unmapElement(element); + } + + /* + * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent) + */ + protected void handleLabelProviderChanged(LabelProviderChangedEvent event) { + Object source= event.getElement(); + if (source == null) { + super.handleLabelProviderChanged(event); + return; + } + + /* + // map the event to the Java elements if possible + // this does not handle the ambiguity of default packages + Object[] mapped= new Object[source.length]; + for (int i= 0; i < source.length; i++) { + Object o= source[i]; + // needs to handle the case of: + // default package + // package fragment root on project + if (o instanceof IResource) { + IResource r= (IResource)o; + IJavaElement element= JavaCore.create(r); + if (element != null) + mapped[i]= element; + else + mapped[i]= o; + } else { + mapped[i]= o; + } + } + super.handleLabelProviderChanged(new LabelProviderChangedEvent((IBaseLabelProvider)event.getSource(), mapped)); */ + super.handleLabelProviderChanged(event); + return; + } + + /** + * @see StructuredViewer#handleInvalidSelection(ISelection, ISelection) + */ + protected void handleInvalidSelection(ISelection invalidSelection, ISelection newSelection) { + super.handleInvalidSelection(invalidSelection, newSelection); + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java new file mode 100644 index 00000000000..f262d5088d6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SWTUtil.java @@ -0,0 +1,103 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DragSource; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Caret; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Widget; + +import org.eclipse.jface.util.Assert; + +/** + * Utility class to simplify access to some SWT resources. + */ +public class SWTUtil { + + /** + * Returns the standard display to be used. The method first checks, if + * the thread calling this method has an associated disaply. If so, this + * display is returned. Otherwise the method returns the default display. + */ + public static Display getStandardDisplay() { + Display display; + display= Display.getCurrent(); + if (display == null) + display= Display.getDefault(); + return display; + } + + /** + * Returns the shell for the given widget. If the widget doesn't represent + * a SWT object that manage a shell, null is returned. + * + * @return the shell for the given widget + */ + public static Shell getShell(Widget widget) { + if (widget instanceof Control) + return ((Control)widget).getShell(); + if (widget instanceof Caret) + return ((Caret)widget).getParent().getShell(); + if (widget instanceof DragSource) + return ((DragSource)widget).getControl().getShell(); + if (widget instanceof DropTarget) + return ((DropTarget)widget).getControl().getShell(); + if (widget instanceof Menu) + return ((Menu)widget).getParent().getShell(); + if (widget instanceof ScrollBar) + return ((ScrollBar)widget).getParent().getShell(); + + return null; + } + + + /** + * Returns a width hint for a button control. + */ + public static int getButtonWidthHint(Button button) { + //PixelConverter converter= new PixelConverter(button); + //int widthHint= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + //return Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + return 8*button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x; + } + + /** + * Returns a height hint for a button control. + */ + public static int getButtonHeigthHint(Button button) { + //PixelConverter converter= new PixelConverter(button); + //return converter.convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT); + return button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y; + } + + + /** + * Sets width and height hint for the button control. + * Note: This is a NOP if the button's layout data is not + * an instance of GridData. + * + * @param the button for which to set the dimension hint + */ + public static void setButtonDimensionHint(Button button) { + Assert.isNotNull(button); + Object gd= button.getLayoutData(); + if (gd instanceof GridData) { + ((GridData)gd).heightHint= getButtonHeigthHint(button); + ((GridData)gd).widthHint= getButtonWidthHint(button); + } + } + + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SelectionUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SelectionUtil.java new file mode 100644 index 00000000000..999183ccc0f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/SelectionUtil.java @@ -0,0 +1,120 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.List; +import java.util.Iterator; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.IStructuredSelection; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; + +/** + * Provides utilities for checking the validity of selections. + *

+ * This class provides static methods only; it is not intended to be instantiated + * or subclassed. + *

+ */ + +public class SelectionUtil { + + /** + * Returns the first element of the given selection. + * Returns null if the selection is empty or if + * the given selection is not of type IStructuredSelection. + * + * @param selection the selection + * @return the selected elements + * + */ + public static Object getFirstElement (ISelection selection) { + if (!(selection instanceof IStructuredSelection)) { + return null; + } + return ((IStructuredSelection)selection).getFirstElement (); + } + + public static Object getSingleElement (ISelection s) { + if (!(s instanceof IStructuredSelection)) + return null; + IStructuredSelection selection= (IStructuredSelection)s; + if (selection.size () != 1) + return null; + return selection.getFirstElement (); + } + + /** + * Returns the elements of the given selection. + * Returns an empty array if the selection is empty or if + * the given selection is not of type IStructuredSelection. + * + * @param selection the selection + * @return the selected elements + * + */ + + public static Object[] toArray(ISelection selection) { + if (!(selection instanceof IStructuredSelection)) { + return new Object[0]; + } + return ((IStructuredSelection)selection).toArray(); + } + + public static List toList(ISelection selection) { + if (selection instanceof IStructuredSelection) { + return ((IStructuredSelection)selection).toList(); + } + return null; + } + + /** + * Returns whether the types of the resources in the given selection are among + * the specified resource types. + * + * @param selection the selection + * @param resourceMask resource mask formed by bitwise OR of resource type + * constants (defined on IResource) + * @return true if all selected elements are resources of the right + * type, and false if at least one element is either a resource + * of some other type or a non-resource + * @see IResource#getType + */ + public static boolean allResourcesAreOfType(IStructuredSelection selection, int resourceMask) { + Iterator resources = selection.iterator(); + while (resources.hasNext()) { + Object next = resources.next(); + if (!(next instanceof IResource)) + return false; + if (!resourceIsType((IResource)next, resourceMask)) + return false; + } + return true; + } + + /** + * Returns whether the type of the given resource is among the specified + * resource types. + * + * @param resource the resource + * @param resourceMask resource mask formed by bitwise OR of resource type + * constants (defined on IResource) + * @return true if the resources has a matching type, and + * false otherwise + * @see IResource#getType + */ + public static boolean resourceIsType(IResource resource, int resourceMask) { + return ((resource != null) && ((resource.getType() & resourceMask) != 0)); + } + + /* (non-Javadoc) + * Private constructor to block instantiation. + */ + private SelectionUtil(){ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/StringMatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/StringMatcher.java new file mode 100644 index 00000000000..6dfa5c748e8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/StringMatcher.java @@ -0,0 +1,390 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Vector; + +public class StringMatcher { + protected String fPattern; + protected int fLength; // pattern length + protected boolean fIgnoreWildCards; + protected boolean fIgnoreCase; + protected boolean fHasLeadingStar; + protected boolean fHasTrailingStar; + protected String fSegments[]; //the given pattern is split into * separated segments + + /* boundary value beyond which we don't need to search in the text */ + protected int fBound= 0; + + protected static final char fSingleWildCard= '\u0000'; + + public static class Position { + int start; //inclusive + int end; //exclusive + public Position(int start, int end) { + this.start= start; + this.end= end; + } + public int getStart() { + return start; + } + public int getEnd() { + return end; + } + } + + /** + * Find the first occurrence of the pattern between startend(exclusive). + * @param text, the String object to search in + * @param start, the starting index of the search range, inclusive + * @param end, the ending index of the search range, exclusive + * @return an StringMatcher.Position object that keeps the starting + * (inclusive) and ending positions (exclusive) of the first occurrence of the + * pattern in the specified range of the text; return null if not found or subtext + * is empty (start==end). A pair of zeros is returned if pattern is empty string + * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc" + * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned + */ + + public StringMatcher.Position find(String text, int start, int end) { + if (fPattern == null || text == null) + throw new IllegalArgumentException(); + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + if (end < 0 || start >= end) + return null; + if (fLength == 0) + return new Position(start, start); + if (fIgnoreWildCards) { + int x= posIn(text, start, end); + if (x < 0) + return null; + return new Position(x, x + fLength); + } + + int segCount= fSegments.length; + if (segCount == 0) //pattern contains only '*'(s) + return new Position(start, end); + + int curPos= start; + int matchStart= -1; + for (int i= 0; i < segCount && curPos < end; ++i) { + String current= fSegments[i]; + int nextMatch= regExpPosIn(text, curPos, end, current); + if (nextMatch < 0) + return null; + if (i == 0) + matchStart= nextMatch; + curPos= nextMatch + current.length(); + } + return new Position(matchStart, curPos); + } + /** + * StringMatcher constructor takes in a String object that is a simple + * pattern which may contain *  for 0 and many characters and + * ?  for exactly one character. Also takes as parameter a boolean object + * specifying if case should be ignored + * @deprecated Use StringMatcher(pattern, ignoreCase, ignoreWildCards). + */ + public StringMatcher(String aPattern, boolean ignoreCase) { + this(aPattern, ignoreCase, false); + } + /** + * StringMatcher constructor takes in a String object that is a simple + * pattern which may contain *  for 0 and many characters and + * ?  for exactly one character. + * + * Literal '*' and '?' characters must be escaped in the pattern + * e.g., "\*" means literal "*", etc. + * + * Escaping any other character (including the escape character itself), + * just results in that character in the pattern. + * e.g., "\a" means "a" and "\\" means "\" + * + * If invoking the StringMatcher with string literals in Java, don't forget + * escape characters are represented by "\\". + * + * @param aPattern the pattern to match text against + * @param ignoreCase if true, case is ignored + * @param ignoreWildCards if true, wild cards and their escape sequences are ignored + * (everything is taken literally). + */ + public StringMatcher(String aPattern, boolean ignoreCase, boolean ignoreWildCards) { + fIgnoreCase= ignoreCase; + fIgnoreWildCards= ignoreWildCards; + fLength= aPattern.length(); + + /* convert case */ + if (fIgnoreCase) { + fPattern= aPattern.toUpperCase(); + } else { + fPattern= aPattern; + } + + if (fIgnoreWildCards) { + parseNoWildCards(); + } else { + parseWildCards(); + } + } + /** + * Given the starting (inclusive) and the ending (exclusive) poisitions in the + * text, determine if the given substring matches with aPattern + * @return true if the specified portion of the text matches the pattern + * @param String text, a String object that contains the substring to match + * @param int start marks the starting position (inclusive) of the substring + * @param int end marks the ending index (exclusive) of the substring + */ + public boolean match(String text, int start, int end) { + if (null == fPattern || null == text) + throw new IllegalArgumentException(); + + if (start > end) + return false; + + if (fIgnoreWildCards) + return fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength); + int segCount= fSegments.length; + if (segCount == 0) //pattern contains only '*'(s) or empty pattern + return true; + if (start == end) + return fLength == 0; + if (fLength == 0) + return start == end; + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + + int tCurPos= start; + int bound= end - fBound; + if (bound < 0) + return false; + int i= 0; + String current= fSegments[i]; + int segLength= current.length(); + + /* process first segment */ + if (!fHasLeadingStar) { + if (!regExpRegionMatches(text, start, current, 0, segLength)) { + return false; + } else { + ++i; + tCurPos= tCurPos + segLength; + } + } + + /* process middle segments */ + for (; i < segCount && tCurPos <= bound; ++i) { + current= fSegments[i]; + int currentMatch; + int k= current.indexOf(fSingleWildCard); + if (k < 0) { + currentMatch= textPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } else { + currentMatch= regExpPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } + tCurPos= currentMatch + current.length(); + } + + /* process final segment */ + if (!fHasTrailingStar && tCurPos != end) { + int clen= current.length(); + return regExpRegionMatches(text, end - clen, current, 0, clen); + } + return i == segCount; + } + /** + * match the given text with the pattern + * @return true if matched eitherwise false + * @param text, a String object + */ + public boolean match(String text) { + return match(text, 0, text.length()); + } + /** + * This method parses the given pattern into segments seperated by wildcard '*' characters. + * Since wildcards are not being used in this case, the pattern consists of a single segment. + */ + private void parseNoWildCards() { + fSegments= new String[1]; + fSegments[0]= fPattern; + fBound= fLength; + } + /** + * This method parses the given pattern into segments seperated by wildcard '*' characters. + * @param p, a String object that is a simple regular expression with *  and/or ?  + */ + private void parseWildCards() { + if (fPattern.startsWith("*")) //$NON-NLS-1$ + fHasLeadingStar= true; + if (fPattern.endsWith("*")) { //$NON-NLS-1$ + /* make sure it's not an escaped wildcard */ + if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') { + fHasTrailingStar= true; + } + } + + Vector temp= new Vector(); + + int pos= 0; + StringBuffer buf= new StringBuffer(); + while (pos < fLength) { + char c= fPattern.charAt(pos++); + switch (c) { + case '\\' : + if (pos >= fLength) { + buf.append(c); + } else { + char next= fPattern.charAt(pos++); + /* if it's an escape sequence */ + if (next == '*' || next == '?' || next == '\\') { + buf.append(next); + } else { + /* not an escape sequence, just insert literally */ + buf.append(c); + buf.append(next); + } + } + break; + case '*' : + if (buf.length() > 0) { + /* new segment */ + temp.addElement(buf.toString()); + fBound += buf.length(); + buf.setLength(0); + } + break; + case '?' : + /* append special character representing single match wildcard */ + buf.append(fSingleWildCard); + break; + default : + buf.append(c); + } + } + + /* add last buffer to segment list */ + if (buf.length() > 0) { + temp.addElement(buf.toString()); + fBound += buf.length(); + } + + fSegments= new String[temp.size()]; + temp.copyInto(fSegments); + } + /** + * @param text, a string which contains no wildcard + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int posIn(String text, int start, int end) { //no wild card in pattern + int max= end - fLength; + + if (!fIgnoreCase) { + int i= text.indexOf(fPattern, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= start; i <= max; ++i) { + if (text.regionMatches(true, i, fPattern, 0, fLength)) + return i; + } + + return -1; + } + /** + * @param text, a simple regular expression that may only contain '?'(s) + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @param p, a simple regular expression that may contains '?' + * @param caseIgnored, wether the pattern is not casesensitive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int regExpPosIn(String text, int start, int end, String p) { + int plen= p.length(); + + int max= end - plen; + for (int i= start; i <= max; ++i) { + if (regExpRegionMatches(text, i, p, 0, plen)) + return i; + } + return -1; + } + /** + * + * @return boolean + * @param text, a String to match + * @param start, int that indicates the starting index of match, inclusive + * @param end int that indicates the ending index of match, exclusive + * @param p, String, String, a simple regular expression that may contain '?' + * @param ignoreCase, boolean indicating wether code>p is case sensitive + */ + protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) { + while (plen-- > 0) { + char tchar= text.charAt(tStart++); + char pchar= p.charAt(pStart++); + + /* process wild cards */ + if (!fIgnoreWildCards) { + /* skip single wild cards */ + if (pchar == fSingleWildCard) { + continue; + } + } + if (pchar == tchar) + continue; + if (fIgnoreCase) { + char tc= Character.toUpperCase(tchar); + if (tc == pchar) + continue; + } + return false; + } + return true; + } + /** + * @param text, the string to match + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @param code>p, a string that has no wildcard + * @param ignoreCase, boolean indicating wether code>p is case sensitive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int textPosIn(String text, int start, int end, String p) { + + int plen= p.length(); + int max= end - plen; + + if (!fIgnoreCase) { + int i= text.indexOf(p, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= 0; i <= max; ++i) { + if (text.regionMatches(true, i, p, 0, plen)) + return i; + } + + return -1; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/TwoArrayQuickSort.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/TwoArrayQuickSort.java new file mode 100644 index 00000000000..5ae29f2f8a1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/TwoArrayQuickSort.java @@ -0,0 +1,69 @@ +package org.eclipse.cdt.internal.ui.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.util.Assert; + + +/** + * Quick sort to sort two arrays in parallel. + */ +public class TwoArrayQuickSort { + + private static void internalSort(String[] keys, Object[] values, int left, int right, boolean ignoreCase) { + + int original_left= left; + int original_right= right; + + String mid= keys[(left + right) / 2]; + do { + while (smaller(keys[left], mid, ignoreCase)) { + left++; + } + while (smaller(mid, keys[right], ignoreCase)) { + right--; + } + if (left <= right) { + String tmp= keys[left]; + keys[left]= keys[right]; + keys[right]= tmp; + + Object tmp2= values[left]; + values[left]= values[right]; + values[right]= tmp2; + + left++; + right--; + } + } while (left <= right); + + if (original_left < right) { + internalSort(keys , values, original_left, right, ignoreCase); + } + if (left < original_right) { + internalSort(keys, values, left, original_right, ignoreCase); + } + } + private static boolean smaller(String left, String right, boolean ignoreCase) { + if (ignoreCase) + return left.compareToIgnoreCase(right) < 0; + else + return left.compareTo(right) < 0; + } + /** + * Sorts keys and values in parallel. + */ + public static void sort(String[] keys, Object[] values, boolean ignoreCase) { + if (keys != null && values != null) { + Assert.isTrue(keys.length == values.length); + if (keys.length > 1) + internalSort(keys, values, 0, keys.length - 1, ignoreCase); + } else { + if (keys != null || values != null) + Assert.isTrue(false, "Either keys or values in null"); //$NON-NLS-1$ + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFileWizardAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFileWizardAction.java new file mode 100644 index 00000000000..b3e66f88e97 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFileWizardAction.java @@ -0,0 +1,68 @@ +package org.eclipse.cdt.internal.ui.wizards; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; + +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.wizards.newresource.BasicNewFileResourceWizard; + +import org.eclipse.cdt.internal.ui.CPlugin; + +public class OpenNewFileWizardAction extends Action implements IWorkbenchWindowActionDelegate { + + + public void run() { + BasicNewFileResourceWizard wizard= new BasicNewFileResourceWizard(); + wizard.init(CPlugin.getDefault().getWorkbench(), getCurrentSelection()); + wizard.setNeedsProgressMonitor(true); + WizardDialog dialog= + new WizardDialog(CPlugin.getActiveWorkbenchShell(), wizard); + dialog.create(); + dialog.getShell().setText( + CPlugin.getResourceString("OpenNewFileWizardAction.title")); //$NON-NLS-1$ + dialog.open(); + } + + + protected IStructuredSelection getCurrentSelection() { + IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + if (window != null) { + ISelection selection= window.getSelectionService().getSelection(); + if (selection instanceof IStructuredSelection) { + return (IStructuredSelection) selection; + } + } + return StructuredSelection.EMPTY; + } + /** + * @see IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + /** + * @see IWorkbenchWindowActionDelegate#dispose() + */ + public void dispose() { + } + /** + * @see IWorkbenchWindowActionDelegate#init(IWorkbenchWindow) + */ + public void init(IWorkbenchWindow window) { + } + /** + * @see IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFolderWizardAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFolderWizardAction.java new file mode 100644 index 00000000000..f2bc57036a1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/OpenNewFolderWizardAction.java @@ -0,0 +1,65 @@ +package org.eclipse.cdt.internal.ui.wizards; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.wizards.newresource.BasicNewFolderResourceWizard; + +import org.eclipse.cdt.internal.ui.CPlugin; + +public class OpenNewFolderWizardAction extends Action implements IWorkbenchWindowActionDelegate { + + public void run() { + BasicNewFolderResourceWizard wizard= new BasicNewFolderResourceWizard(); + wizard.init(CPlugin.getDefault().getWorkbench(), getCurrentSelection()); + wizard.setNeedsProgressMonitor(true); + WizardDialog dialog= + new WizardDialog(CPlugin.getActiveWorkbenchShell(), wizard); + dialog.create(); + dialog.getShell().setText( + CPlugin.getResourceString("OpenNewFolderWizardAction.title")); //$NON-NLS-1$ + dialog.open(); + } + + protected IStructuredSelection getCurrentSelection() { + IWorkbenchWindow window= CPlugin.getActiveWorkbenchWindow(); + if (window != null) { + ISelection selection= window.getSelectionService().getSelection(); + if (selection instanceof IStructuredSelection) { + return (IStructuredSelection) selection; + } + } + return StructuredSelection.EMPTY; + } + /** + * @see IActionDelegate#run(IAction) + */ + public void run(IAction action) { + run(); + } + /** + * @see IWorkbenchWindowActionDelegate#dispose() + */ + public void dispose() { + } + /** + * @see IWorkbenchWindowActionDelegate#init(IWorkbenchWindow) + */ + public void init(IWorkbenchWindow window) { + } + /** + * @see IActionDelegate#selectionChanged(IAction, ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/DialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/DialogField.java new file mode 100644 index 00000000000..813c77a81b5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/DialogField.java @@ -0,0 +1,138 @@ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; + +import org.eclipse.jface.util.Assert; + +import org.eclipse.cdt.internal.ui.wizards.swt.MGridData; + +public class DialogField { + + private Label fLabel; + protected String fLabelText; + + private IDialogFieldListener fDialogFieldListener; + + private boolean fEnabled; + + protected final void assertCompositeNotNull(Composite comp) { + Assert.isNotNull(comp, "uncreated control requested with composite null"); //$NON-NLS-1$ + } + protected final void assertEnoughColumns(int nColumns) { + Assert.isTrue(nColumns >= getNumberOfControls(), "given number of columns is too small"); //$NON-NLS-1$ + } + public static Control createEmptySpace(Composite parent, int span) { + Label label= new Label(parent, SWT.LEFT); + MGridData gd= new MGridData(); + gd.horizontalAlignment= gd.BEGINNING; + gd.grabExcessHorizontalSpace= false; + gd.horizontalSpan= span; + gd.horizontalIndent= 0; + gd.widthHint= 0; + gd.heightHint= 0; + label.setLayoutData(gd); + return label; + } + public static Control createEmptySpace(Composite parent) { + return createEmptySpace(parent, 1); + } + public void dialogFieldChanged() { + if (fDialogFieldListener != null) { + fDialogFieldListener.dialogFieldChanged(this); + } + } + // ------- layout helpers + + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label= getLabelControl(parent); + label.setLayoutData(gridDataForLabel(nColumns)); + + return new Control[] { label }; + } + // ------- ui creation + + public Label getLabelControl(Composite parent) { + if (fLabel == null) { + assertCompositeNotNull(parent); + + fLabel= new Label(parent, SWT.LEFT); + fLabel.setFont(parent.getFont()); + fLabel.setEnabled(fEnabled); + if (fLabelText != null && !"".equals(fLabelText)) { //$NON-NLS-1$ + fLabel.setText(fLabelText); + } else { + // XXX: to avoid a 16 pixel wide empty label - revisit + fLabel.setText("."); //$NON-NLS-1$ + fLabel.setVisible(false); + } + } + return fLabel; + } + public int getNumberOfControls() { + return 1; + } + protected static MGridData gridDataForLabel(int span) { + MGridData gd= new MGridData(); + gd.horizontalSpan= span; + return gd; + } + public boolean isEnabled() { + return fEnabled; + } + protected boolean isOkToUse(Control control) { + return (control != null) && !(control.isDisposed()); + } + public void postSetFocusOnDialogField(Display display) { + if (display != null) { + display.asyncExec( + new Runnable() { + public void run() { + setFocus(); + } + } + ); + } + } + // ------ change listener + + public void setDialogFieldListener(IDialogFieldListener listener) { + fDialogFieldListener= listener; + } + // --------- enable / disable management + + public void setEnabled(boolean enabled) { + if (enabled != fEnabled) { + fEnabled= enabled; + updateEnableState(); + } + } + // ------- focus management + + public boolean setFocus() { + return false; + } + public void setLabelText(String labeltext) { + fLabelText= labeltext; + } + protected void updateEnableState() { + if (fLabel != null) { + fLabel.setEnabled(fEnabled); + } + } + public DialogField() { + fEnabled= true; + fLabel= null; + fLabelText= ""; //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java new file mode 100644 index 00000000000..65ef15bc79f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IDialogFieldListener.java @@ -0,0 +1,11 @@ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +public interface IDialogFieldListener { + + void dialogFieldChanged(DialogField field); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java new file mode 100644 index 00000000000..0f59e6736e1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/IStringButtonAdapter.java @@ -0,0 +1,11 @@ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +public interface IStringButtonAdapter { + + void changeControlPressed(DialogField field); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java new file mode 100644 index 00000000000..16e02e7746a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringButtonDialogField.java @@ -0,0 +1,100 @@ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.cdt.internal.ui.wizards.swt.MGridData; + +public class StringButtonDialogField extends StringDialogField { + + private Button fBrowseButton; + private String fBrowseButtonLabel; + private IStringButtonAdapter fStringButtonAdapter; + + private boolean fButtonEnabled; + + // ------ adapter communication + + public void changeControlPressed() { + fStringButtonAdapter.changeControlPressed(this); + } + // ------- layout helpers + + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label= getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Text text= getTextControl(parent); + text.setLayoutData(gridDataForText(nColumns - 2)); + Control button= getChangeControl(parent); + button.setLayoutData(gridDataForControl(1)); + + return new Control[] { label, text, button }; + } + // ------ enable / disable management + + public void enableButton(boolean enable) { + if (isOkToUse(fBrowseButton)) { + fBrowseButton.setEnabled(isEnabled() && enable); + } + fButtonEnabled= enable; + } + // ------- ui creation + + public Control getChangeControl(Composite parent) { + if (fBrowseButton == null) { + assertCompositeNotNull(parent); + + fBrowseButton= new Button(parent, SWT.PUSH); + fBrowseButton.setText(fBrowseButtonLabel); + fBrowseButton.setEnabled(isEnabled() && fButtonEnabled); + fBrowseButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + changeControlPressed(); + } + public void widgetSelected(SelectionEvent e) { + changeControlPressed(); + } + }); + + } + return fBrowseButton; + } + public int getNumberOfControls() { + return 3; + } + protected static MGridData gridDataForControl(int span) { + MGridData gd= new MGridData(); + gd.horizontalAlignment= gd.FILL; + gd.grabExcessHorizontalSpace= false; + gd.horizontalSpan= span; + return gd; + } + public StringButtonDialogField(IStringButtonAdapter adapter) { + super(); + fStringButtonAdapter= adapter; + fBrowseButtonLabel= "!Browse...!"; //$NON-NLS-1$ + fButtonEnabled= true; + } + public void setButtonLabel(String label) { + fBrowseButtonLabel= label; + } + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fBrowseButton)) { + fBrowseButton.setEnabled(isEnabled() && fButtonEnabled); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringDialogField.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringDialogField.java new file mode 100644 index 00000000000..1728d8a1b00 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/dialogfields/StringDialogField.java @@ -0,0 +1,127 @@ +package org.eclipse.cdt.internal.ui.wizards.dialogfields; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.cdt.internal.ui.wizards.swt.MGridData; + + +public class StringDialogField extends DialogField { + + private String fText; + private Text fTextControl; + private ModifyListener fModifyListener; + + // ------- layout helpers + + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label= getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Text text= getTextControl(parent); + text.setLayoutData(gridDataForText(nColumns - 1)); + + return new Control[] { label, text }; + } + private void doModifyText(ModifyEvent e) { + if (isOkToUse(fTextControl)) { + fText= fTextControl.getText(); + } + dialogFieldChanged(); + } + public int getNumberOfControls() { + return 2; + } + // ------- ui creation + + public Text getTextControl(Composite parent) { + if (fTextControl == null) { + assertCompositeNotNull(parent); + fModifyListener= new ModifyListener() { + public void modifyText(ModifyEvent e) { + doModifyText(e); + } + }; + + fTextControl= new Text(parent, SWT.SINGLE | SWT.BORDER); + // moved up due to 1GEUNW2 + fTextControl.setText(fText); + fTextControl.setFont(parent.getFont()); + fTextControl.addModifyListener(fModifyListener); + + + fTextControl.setEnabled(isEnabled()); + } + return fTextControl; + } + // ------ text access + + /** + * Get the text + */ + public String getText() { + return fText; + } + protected static MGridData gridDataForText(int span) { + MGridData gd= new MGridData(); + gd.horizontalAlignment= gd.FILL; + gd.grabExcessHorizontalSpace= true; + gd.grabColumn= 0; + gd.horizontalSpan= span; + return gd; + } + // ------- focus methods + + public boolean setFocus() { + if (isOkToUse(fTextControl)) { + fTextControl.setFocus(); + fTextControl.setSelection(0, fTextControl.getText().length()); + } + return true; + } + /** + * Set the text. Triggers an dialog-changed event + */ + public void setText(String text) { + fText= text; + if (isOkToUse(fTextControl)) { + fTextControl.setText(text); + } else { + dialogFieldChanged(); + } + } + /** + * Set the text without triggering a dialog-changed event + */ + public void setTextWithoutUpdate(String text) { + fText= text; + if (isOkToUse(fTextControl)) { + fTextControl.removeModifyListener(fModifyListener); + fTextControl.setText(text); + fTextControl.addModifyListener(fModifyListener); + } + } + // ------ enable / disable management + + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fTextControl)) { + fTextControl.setEnabled(isEnabled()); + } + } + public StringDialogField() { + super(); + fText= ""; //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridData.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridData.java new file mode 100644 index 00000000000..7d8254c884f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridData.java @@ -0,0 +1,171 @@ +package org.eclipse.cdt.internal.ui.wizards.swt; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.swt.SWT; + +public final class MGridData { + /** + * verticalAlignment specifies how controls will be positioned + * vertically within a cell. + * + * The default value is CENTER. + * + * Possible values are: + * + * BEGINNING: Position the control at the top of the cell + * CENTER: Position the control in the vertical center of the cell + * END: Position the control at the bottom of the cell + * FILL: Resize the control to fill the cell vertically + */ + public int verticalAlignment= CENTER; + /** + * horizontalAlignment specifies how controls will be positioned + * horizontally within a cell. + * + * The default value is BEGINNING. + * + * Possible values are: + * + * BEGINNING: Position the control at the left of the cell + * CENTER: Position the control in the horizontal center of the cell + * END: Position the control at the right of the cell + * FILL: Resize the control to fill the cell horizontally + */ + public int horizontalAlignment= BEGINNING; + /** + * widthHint specifies a minimum width for the column. A value of + * SWT.DEFAULT indicates that no minimum width is specified. + * + * The default value is SWT.DEFAULT. + */ + public int widthHint= SWT.DEFAULT; + /** + * heightHint specifies a minimum height for the row. A value of + * SWT.DEFAULT indicates that no minimum height is specified. + * + * The default value is SWT.DEFAULT. + */ + public int heightHint= SWT.DEFAULT; + /** + * horizontalIndent specifies the number of pixels of indentation + * that will be placed along the left side of the cell. + * + * The default value is 0. + */ + public int horizontalIndent= 0; + /** + * horizontalSpan specifies the number of column cells that the control + * will take up. + * + * The default value is 1. + */ + public int horizontalSpan= 1; + /** + * verticalSpan specifies the number of row cells that the control + * will take up. + * + * The default value is 1. + */ + public int verticalSpan= 1; + /** + * grabExcessHorizontalSpace specifies whether the cell will be made + * wide enough to fit the remaining horizontal space. + * + * The default value is false. + */ + public boolean grabExcessHorizontalSpace= false; + /** + * grabExcessVerticalSpace specifies whether the cell will be made + * tall enough to fit the remaining vertical space. + * + * The default value is false. + */ + public boolean grabExcessVerticalSpace= false; + + + // --------- added to original GridData -------- + + /** + * if a span is defined that is also grabing, this defines the column that + * will grab the space + * + * The default value is -1, which will result in the default behavior + * (=last culumn) + */ + public int grabColumn= -1; + + /** + * If a span is defined that is also grabing, this defines the row that + * will grab + * + * The default value is -1, which will result in the default behavior + * (=last row) + */ + public int grabRow= -1; + + // Alignment constants. + public static final int BEGINNING= 1; + public static final int CENTER= 2; + public static final int END= 3; + public static final int FILL= 4; + + // Style constants + public static final int VERTICAL_ALIGN_BEGINNING= 1 << 1; + public static final int VERTICAL_ALIGN_CENTER= 1 << 2; + public static final int VERTICAL_ALIGN_END= 1 << 3; + public static final int VERTICAL_ALIGN_FILL= 1 << 4; + public static final int HORIZONTAL_ALIGN_BEGINNING= 1 << 5; + public static final int HORIZONTAL_ALIGN_CENTER= 1 << 6; + public static final int HORIZONTAL_ALIGN_END= 1 << 7; + public static final int HORIZONTAL_ALIGN_FILL= 1 << 8; + public static final int GRAB_HORIZONTAL= 1 << 9; + public static final int GRAB_VERTICAL= 1 << 10; + + // Private + int childIndex; + boolean isItemData= true; + boolean isItemData() { + return isItemData; + } + boolean isSpacerData() { + return !isItemData; + } + public MGridData(int style) { + super(); + + if ((style & VERTICAL_ALIGN_BEGINNING) != 0) + verticalAlignment= BEGINNING; + if ((style & VERTICAL_ALIGN_CENTER) != 0) + verticalAlignment= CENTER; + if ((style & VERTICAL_ALIGN_FILL) != 0) + verticalAlignment= FILL; + if ((style & VERTICAL_ALIGN_END) != 0) + verticalAlignment= END; + + if ((style & HORIZONTAL_ALIGN_BEGINNING) != 0) + horizontalAlignment= BEGINNING; + if ((style & HORIZONTAL_ALIGN_CENTER) != 0) + horizontalAlignment= CENTER; + if ((style & HORIZONTAL_ALIGN_FILL) != 0) + horizontalAlignment= FILL; + if ((style & HORIZONTAL_ALIGN_END) != 0) + horizontalAlignment= END; + + if ((style & GRAB_HORIZONTAL) != 0) + grabExcessHorizontalSpace= true; + else + grabExcessHorizontalSpace= false; + if ((style & GRAB_VERTICAL) != 0) + grabExcessVerticalSpace= true; + else + grabExcessVerticalSpace= false; + + } + public MGridData() { + super(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridLayout.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridLayout.java new file mode 100644 index 00000000000..e75d34d4be1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/swt/MGridLayout.java @@ -0,0 +1,682 @@ +package org.eclipse.cdt.internal.ui.wizards.swt; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Layout; + +public final class MGridLayout extends Layout { + /** + * marginWidth specifies the number of pixels of horizontal margin + * that will be placed along the left and right edges of the layout. + * + * The default value is 5. + */ + public int marginWidth= 5; + /** + * marginHeight specifies the number of pixels of vertical margin + * that will be placed along the top and bottom edges of the layout. + * + * The default value is 5. + */ + public int marginHeight= 5; + /** + * numColumns specifies the number of cell columns in the layout. + * + * The default value is 1. + */ + public int numColumns= 1; + /** + * makeColumnsEqualWidth specifies whether all columns in the layout + * will be forced to have the same width. + * + * The default value is false. + */ + public boolean makeColumnsEqualWidth= false; + /** + * horizontalSpacing specifies the number of pixels between the right + * edge of one cell and the left edge of its neighbouring cell to + * the right. + * + * The default value is 5. + */ + public int horizontalSpacing= 5; + /** + * verticalSpacing specifies the number of pixels between the bottom + * edge of one cell and the top edge of its neighbouring cell underneath. + * + * The default value is 5. + */ + public int verticalSpacing= 5; + + + // --------- added to original GridLayout -------- + + /** + * minimumWidth specifies a minimum width of this layout + * If SWT.DEFAULT is set, no minimum width is forced + * + * The default value is SWT.DEFAULT. + */ + public int minimumWidth= SWT.DEFAULT; + /** + * minimumHeight specifies a minimum height of this layout + * If SWT.DEFAULT is set, no minimum height is forced + * + * The default value is SWT.DEFAULT. + */ + public int minimumHeight= SWT.DEFAULT; + + /** + * id specifies an identifier string for this layout. + */ + public String id; + + // Private variables. Cached values used to cut down on grid calculations. + boolean initialLayout= true; + Vector grid= new Vector(); + int[] pixelColumnWidths; + int[] pixelRowHeights; + int[] expandableColumns; + int[] expandableRows; + void adjustGridDimensions(Composite composite, boolean flushCache) { + // Ensure that widgets that span more than one row or column have enough space. + for (int row= 0; row < grid.size(); row++) { + for (int column= 0; column < numColumns; column++) { + MGridData spec= ((MGridData[]) grid.elementAt(row))[column]; + if (spec.isItemData()) { + // Widgets spanning columns. + if (spec.horizontalSpan > 1) { + Control child= composite.getChildren()[spec.childIndex]; + Point extent= child.computeSize(spec.widthHint, spec.heightHint, flushCache); + + // Calculate the size of the widget's spanned columns. + int lastSpanIndex= column + spec.horizontalSpan; + int spannedSize= 0; + for (int c= column; c < lastSpanIndex; c++) { + spannedSize= spannedSize + pixelColumnWidths[c] + horizontalSpacing; + } + spannedSize= spannedSize - horizontalSpacing; + + // If the spanned columns are not large enough to display the widget, adjust the column + // sizes to account for the extra space that is needed. + if (extent.x + spec.horizontalIndent > spannedSize) { + int extraSpaceNeeded= extent.x + spec.horizontalIndent - spannedSize; + int lastColumn= column + spec.horizontalSpan - 1; + int colWidth; + if (makeColumnsEqualWidth) { + // Evenly distribute the extra space amongst all of the columns. + int columnExtra= extraSpaceNeeded / numColumns; + int columnRemainder= extraSpaceNeeded % numColumns; + for (int i= 0; i < pixelColumnWidths.length; i++) { + colWidth= pixelColumnWidths[i] + columnExtra; + pixelColumnWidths[i]= colWidth; + } + colWidth= pixelColumnWidths[lastColumn] + columnRemainder; + pixelColumnWidths[lastColumn]= colWidth; + } else { + Vector localExpandableColumns= new Vector(); + for (int i= column; i < lastColumn; i++) { + for (int j= 0; j < expandableColumns.length; j++) { + if (expandableColumns[j] == i) { + localExpandableColumns.addElement(new Integer(i)); + } + } + } + if (localExpandableColumns.size() > 0) { + // If any of the widget's columns grab excess space, allocate the space amongst those columns. + int columnExtra= extraSpaceNeeded / localExpandableColumns.size(); + int columnRemainder= extraSpaceNeeded % localExpandableColumns.size(); + for (int i= 0; i < localExpandableColumns.size(); i++) { + int expandableCol= ((Integer) localExpandableColumns.elementAt(i)).intValue(); + colWidth= pixelColumnWidths[expandableCol] + columnExtra; + pixelColumnWidths[expandableCol]= colWidth; + } + colWidth= pixelColumnWidths[lastColumn] + columnRemainder; + pixelColumnWidths[lastColumn]= colWidth; + } else { + // Add the extra space to the widget's last column if none of its columns grab excess space. + colWidth= pixelColumnWidths[lastColumn] + extraSpaceNeeded; + pixelColumnWidths[lastColumn]= colWidth; + } + } + } + } + + // Widgets spanning rows. + if (spec.verticalSpan > 1) { + Control child= composite.getChildren()[spec.childIndex]; + Point extent= child.computeSize(spec.widthHint, spec.heightHint, flushCache); + + // Calculate the size of the widget's spanned rows. + int lastSpanIndex= row + spec.verticalSpan; + int spannedSize= 0; + for (int r= row; r < lastSpanIndex; r++) { + spannedSize= spannedSize + pixelRowHeights[r] + verticalSpacing; + } + spannedSize= spannedSize - verticalSpacing; + // If the spanned rows are not large enough to display the widget, adjust the row + // sizes to account for the extra space that is needed. + if (extent.y > spannedSize) { + int extraSpaceNeeded= extent.y - spannedSize; + int lastRow= row + spec.verticalSpan - 1; + int rowHeight; + Vector localExpandableRows= new Vector(); + for (int i= row; i < lastRow; i++) { + for (int j= 0; j < expandableRows.length; j++) { + if (expandableRows[j] == i) { + localExpandableRows.addElement(new Integer(i)); + } + } + } + if (localExpandableRows.size() > 0) { + // If any of the widget's rows grab excess space, allocate the space amongst those rows. + int rowExtra= extraSpaceNeeded / localExpandableRows.size(); + int rowRemainder= extraSpaceNeeded % localExpandableRows.size(); + for (int i= 0; i < localExpandableRows.size(); i++) { + int expandableRow= ((Integer) localExpandableRows.elementAt(i)).intValue(); + rowHeight= pixelRowHeights[expandableRow] + rowExtra; + pixelRowHeights[expandableRow]= rowHeight; + } + rowHeight= pixelRowHeights[lastRow] + rowRemainder; + pixelRowHeights[lastRow]= rowHeight; + } else { + // Add the extra space to the widget's last row if no rows grab excess space. + rowHeight= pixelRowHeights[lastRow] + extraSpaceNeeded; + pixelRowHeights[lastRow]= rowHeight; + } + } + } + } + } + } + } + void calculateGridDimensions(Composite composite, boolean flushCache) { + int maxWidth, childWidth, maxHeight, childHeight; + + // + Control[] children= composite.getChildren(); + Point[] childSizes= new Point[children.length]; + pixelColumnWidths= new int[numColumns]; + pixelRowHeights= new int[grid.size()]; + + // Loop through the grid by column to get the width that each column needs to be. + // Each column will be as wide as its widest widget. + for (int column= 0; column < numColumns; column++) { + maxWidth= 0; + for (int row= 0; row < grid.size(); row++) { + MGridData spec= ((MGridData[]) grid.elementAt(row))[column]; + if (spec.isItemData()) { + Control child= children[spec.childIndex]; + childSizes[spec.childIndex]= child.computeSize(spec.widthHint, spec.heightHint, flushCache); + childWidth= childSizes[spec.childIndex].x + spec.horizontalIndent; + if (spec.horizontalSpan == 1) { + maxWidth= Math.max(maxWidth, childWidth); + } + } + } + // Cache the values for later use. + pixelColumnWidths[column]= maxWidth; + } + + // + if (makeColumnsEqualWidth) { + maxWidth= 0; + // Find the largest column size that is necessary and make each column that size. + for (int i= 0; i < numColumns; i++) { + maxWidth= Math.max(maxWidth, pixelColumnWidths[i]); + } + for (int i= 0; i < numColumns; i++) { + pixelColumnWidths[i]= maxWidth; + } + } + + // Loop through the grid by row to get the height that each row needs to be. + // Each row will be as high as its tallest widget. + for (int row= 0; row < grid.size(); row++) { + maxHeight= 0; + for (int column= 0; column < numColumns; column++) { + MGridData spec= ((MGridData[]) grid.elementAt(row))[column]; + if (spec.isItemData()) { + childHeight= childSizes[spec.childIndex].y; + if (spec.verticalSpan == 1) { + maxHeight= Math.max(maxHeight, childHeight); + } + } + } + // Cache the values for later use. + pixelRowHeights[row]= maxHeight; + } + } + void computeExpandableCells() { + // If a widget grabs excess horizontal space, the last column that the widget spans + // will be expandable. Similarly, if a widget grabs excess vertical space, the + // last row that the widget spans will be expandable. + Hashtable growColumns= new Hashtable(); + Hashtable growRows= new Hashtable(); + for (int col= 0; col < numColumns; col++) { + for (int row= 0; row < grid.size(); row++) { + MGridData spec= ((MGridData[]) grid.elementAt(row))[col]; + if (spec.grabExcessHorizontalSpace) { + if (spec.grabColumn >= 0 && spec.grabColumn < spec.horizontalSpan) { + growColumns.put(new Integer(col + spec.grabColumn), new Object()); + } else { + growColumns.put(new Integer(col + spec.horizontalSpan - 1), new Object()); + } + } + if (spec.grabExcessVerticalSpace) { + if (spec.grabRow >= 0 && spec.grabRow < spec.verticalSpan) { + growRows.put(new Integer(row + spec.grabRow), new Object()); + } else { + growRows.put(new Integer(row + spec.verticalSpan - 1), new Object()); + } + } + } + } + + // Cache the values. These values are used later during children layout. + int i= 0; + Enumeration enum= growColumns.keys(); + expandableColumns= new int[growColumns.size()]; + while (enum.hasMoreElements()) { + expandableColumns[i]= ((Integer) enum.nextElement()).intValue(); + i= i + 1; + } + i= 0; + enum= growRows.keys(); + expandableRows= new int[growRows.size()]; + while (enum.hasMoreElements()) { + expandableRows[i]= ((Integer) enum.nextElement()).intValue(); + i= i + 1; + } + } + Point computeLayoutSize(Composite composite, int wHint, int hHint, boolean flushCache) { + int totalMarginHeight, totalMarginWidth; + int totalWidth, totalHeight; + int cols, rows; + + // Initialize the grid and other cached information that help with the grid layout. + if (grid.size() == 0) { + createGrid(composite); + calculateGridDimensions(composite, flushCache); + computeExpandableCells(); + adjustGridDimensions(composite, flushCache); + } + + // + cols= numColumns; + rows= grid.size(); + totalMarginHeight= marginHeight + composite.getBorderWidth(); + totalMarginWidth= marginWidth + composite.getBorderWidth(); + + // The total width is the margin plus border width plus space between each column, + // plus the width of each column. + totalWidth= (totalMarginWidth * 2) + ((cols - 1) * horizontalSpacing); + + //Add up the width of each column. + for (int i= 0; i < pixelColumnWidths.length; i++) { + totalWidth= totalWidth + pixelColumnWidths[i]; + } + + // The total height is the margin plus border height, plus space between each row, + // plus the height of the tallest child in each row. + totalHeight= (totalMarginHeight * 2) + ((rows - 1) * verticalSpacing); + + //Add up the height of each row. + for (int i= 0; i < pixelRowHeights.length; i++) { + totalHeight= totalHeight + pixelRowHeights[i]; + } + + if (wHint != SWT.DEFAULT) { + totalWidth= wHint; + }; + if (hHint != SWT.DEFAULT) { + totalHeight= hHint; + }; + // The preferred extent is the width and height that will accomodate the grid's widgets. + return new Point(totalWidth, totalHeight); + } + protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { + + if (composite.getChildren().length == 0) + return new Point(0, 0); + + // Make sure that all of the composite children have a layout spec. Do this by + // using the initialLayout flag. + if (flushCache) + initialLayout= true; + if (initialLayout) { + initializeLayoutData(composite); + initialLayout= false; + } + + if (flushCache) { + // Cause the grid and its related information to be calculated + // again. + grid.removeAllElements(); + } + + Point size= computeLayoutSize(composite, wHint, hHint, flushCache); + if (minimumWidth != SWT.DEFAULT && size.x < minimumWidth) { + size.x= minimumWidth; + } + if (minimumHeight != SWT.DEFAULT && size.y < minimumHeight) { + size.y= minimumHeight; + } + return size; + } + void createGrid(Composite composite) { + int row, column, rowFill, columnFill; + Control[] children; + MGridData spacerSpec; + + // + children= composite.getChildren(); + + // + grid.addElement(emptyRow()); + row= 0; + column= 0; + + // Loop through the children and place their associated layout specs in the + // grid. Placement occurs left to right, top to bottom (i.e., by row). + for (int i= 0; i < children.length; i++) { + // Find the first available spot in the grid. + Control child= children[i]; + MGridData spec= (MGridData) child.getLayoutData(); + while (((MGridData[]) grid.elementAt(row))[column] != null) { + column= column + 1; + if (column >= numColumns) { + row= row + 1; + column= 0; + if (row >= grid.size()) { + grid.addElement(emptyRow()); + } + } + } + // See if the place will support the widget's horizontal span. If not, go to the + // next row. + if (column + spec.horizontalSpan - 1 >= numColumns) { + grid.addElement(emptyRow()); + row= row + 1; + column= 0; + } + + // The vertical span for the item will be at least 1. If it is > 1, + // add other rows to the grid. + for (int j= 2; j <= spec.verticalSpan; j++) { + if (row + j > grid.size()) { + grid.addElement(emptyRow()); + } + } + + // Store the layout spec. Also cache the childIndex. NOTE: That we assume the children of a + // composite are maintained in the order in which they are created and added to the composite. + ((MGridData[]) grid.elementAt(row))[column]= spec; + spec.childIndex= i; + + // Put spacers in the grid to account for the item's vertical and horizontal + // span. + rowFill= spec.verticalSpan - 1; + columnFill= spec.horizontalSpan - 1; + for (int r= 1; r <= rowFill; r++) { + for (int c= 0; c < spec.horizontalSpan; c++) { + spacerSpec= new MGridData(); + spacerSpec.isItemData= false; + ((MGridData[]) grid.elementAt(row + r))[column + c]= spacerSpec; + } + } + for (int c= 1; c <= columnFill; c++) { + for (int r= 0; r < spec.verticalSpan; r++) { + spacerSpec= new MGridData(); + spacerSpec.isItemData= false; + ((MGridData[]) grid.elementAt(row + r))[column + c]= spacerSpec; + } + } + column= column + spec.horizontalSpan - 1; + } + + // Fill out empty grid cells with spacers. + for (int k= column + 1; k < numColumns; k++) { + spacerSpec= new MGridData(); + spacerSpec.isItemData= false; + ((MGridData[]) grid.elementAt(row))[k]= spacerSpec; + } + for (int k= row + 1; k < grid.size(); k++) { + spacerSpec= new MGridData(); + spacerSpec.isItemData= false; + ((MGridData[]) grid.elementAt(k))[column]= spacerSpec; + } + } + MGridData[] emptyRow() { + MGridData[] row= new MGridData[numColumns]; + for (int i= 0; i < numColumns; i++) { + row[i]= null; + } + return row; + } + void initializeLayoutData(Composite composite) { + Control[] children= composite.getChildren(); + for (int i= 0; i < children.length; i++) { + Control child= children[i]; + if (child.getLayoutData() == null) { + child.setLayoutData(new MGridData()); + } + } + } + protected void layout(Composite composite, boolean flushCache) { + //System.out.println("start layout " + id); + //new Error (). printStackTrace(); + int[] columnWidths; + int[] rowHeights; + int rowSize, rowY, columnX; + int compositeWidth, compositeHeight; + int excessHorizontal, excessVertical; + Control[] children; + if (flushCache) { + // Cause the grid and its related information to be calculated + // again. + grid.removeAllElements(); + } + children= composite.getChildren(); + if (children.length == 0) + return; + + // + Point extent= computeLayoutSize(composite, SWT.DEFAULT, SWT.DEFAULT, flushCache); + columnWidths= new int[numColumns]; + for (int i= 0; i < pixelColumnWidths.length; i++) { + columnWidths[i]= pixelColumnWidths[i]; + } + rowHeights= new int[grid.size()]; + for (int i= 0; i < pixelRowHeights.length; i++) { + rowHeights[i]= pixelRowHeights[i]; + } + int columnWidth= 0; + rowSize= Math.max(1, grid.size()); + + // + compositeWidth= extent.x; + compositeHeight= extent.y; + + // Calculate whether or not there is any extra space or not enough space due to a resize + // operation. Then allocate/deallocate the space to columns and rows that are expandable. + // If a widget grabs excess space, its last column or row will be expandable. + excessHorizontal= composite.getClientArea().width - compositeWidth; + excessVertical= composite.getClientArea().height - compositeHeight; + + // Allocate/deallocate horizontal space. + if (expandableColumns.length != 0) { + int excess, remainder, last; + int colWidth; + excess= excessHorizontal / expandableColumns.length; + remainder= excessHorizontal % expandableColumns.length; + last= 0; + for (int i= 0; i < expandableColumns.length; i++) { + int expandableCol= expandableColumns[i]; + colWidth= columnWidths[expandableCol]; + colWidth= colWidth + excess; + columnWidths[expandableCol]= colWidth; + last= Math.max(last, expandableCol); + } + colWidth= columnWidths[last]; + colWidth= colWidth + remainder; + columnWidths[last]= colWidth; + } + + // Go through all specs in each expandable column and get the maximum specified + // widthHint. Use this as the minimumWidth for the column. + for (int i= 0; i < expandableColumns.length; i++) { + int expandableCol= expandableColumns[i]; + int colWidth= columnWidths[expandableCol]; + int minWidth= 0; + for (int j= 0; j < grid.size(); j++) { + MGridData[] row= (MGridData[]) grid.elementAt(j); + MGridData spec= row[expandableCol]; + minWidth= Math.max(minWidth, spec.widthHint); + } + columnWidths[expandableCol]= Math.max(colWidth, minWidth); + } + // Allocate/deallocate vertical space. + if (expandableRows.length != 0) { + int excess, remainder, last; + int rowHeight; + excess= excessVertical / expandableRows.length; + remainder= excessVertical % expandableRows.length; + last= 0; + for (int i= 0; i < expandableRows.length; i++) { + int expandableRow= expandableRows[i]; + rowHeight= rowHeights[expandableRow]; + rowHeight= rowHeight + excess; + rowHeights[expandableRow]= rowHeight; + last= Math.max(last, expandableRow); + } + rowHeight= rowHeights[last]; + rowHeight= rowHeight + remainder; + rowHeights[last]= rowHeight; + } + // Go through all specs in each expandable row and get the maximum specified + // heightHint. Use this as the minimumHeight for the row. + for (int i= 0; i < expandableRows.length; i++) { + int expandableRow= expandableRows[i]; + int rowHeight= rowHeights[expandableRow]; + int minHeight= 0; + MGridData[] row= (MGridData[]) grid.elementAt(expandableRow); + for (int j= 0; j < numColumns; j++) { + MGridData spec= row[j]; + minHeight= Math.max(minHeight, spec.heightHint); + } + rowHeights[expandableRow]= Math.max(rowHeight, minHeight); + } + + // Get the starting x and y. + columnX= marginWidth + composite.getBorderWidth() + composite.getClientArea().x; + rowY= marginHeight + composite.getBorderWidth() + composite.getClientArea().y; + + // Layout the widget left to right, top to bottom. + for (int r= 0; r < rowSize; r++) { + int rowHeight= rowHeights[r]; + MGridData[] row= (MGridData[]) grid.elementAt(r); + + // + for (int c= 0; c < row.length; c++) { + int spannedWidth= 0, spannedHeight= 0; + int hAlign= 0, vAlign= 0; + int widgetX= 0, widgetY= 0; + int widgetW= 0, widgetH= 0; + + // + MGridData spec= (MGridData) row[c]; + if (makeColumnsEqualWidth) { + columnWidth= composite.getBounds().width - ((marginWidth + composite.getBorderWidth()) * 2) - ((numColumns - 1) * horizontalSpacing); + columnWidth= columnWidth / numColumns; + for (int i= 0; i < columnWidths.length; i++) { + columnWidths[i]= columnWidth; + } + } else { + columnWidth= columnWidths[c]; + } + + // + spannedWidth= columnWidth; + for (int k= 1; k < spec.horizontalSpan; k++) { + if ((c + k) <= numColumns) { + if (!makeColumnsEqualWidth) { + columnWidth= columnWidths[c + k]; + } + spannedWidth= spannedWidth + columnWidth + horizontalSpacing; + } + } + + // + spannedHeight= rowHeight; + for (int k= 1; k < spec.verticalSpan; k++) { + if ((r + k) <= grid.size()) { + spannedHeight= spannedHeight + rowHeights[r + k] + verticalSpacing; + } + } + + // + if (spec.isItemData()) { + Control child= children[spec.childIndex]; + Point childExtent= child.computeSize(spec.widthHint, spec.heightHint, flushCache); + hAlign= spec.horizontalAlignment; + widgetX= columnX; + + // Calculate the x and width values for the widget. + if (hAlign == spec.CENTER) { + widgetX= widgetX + (spannedWidth / 2) - (childExtent.x / 2); + } else if (hAlign == spec.END) { + widgetX= widgetX + spannedWidth - childExtent.x - spec.horizontalIndent; + } else { + widgetX= widgetX + spec.horizontalIndent; + } + if (hAlign == spec.FILL) { + widgetW= spannedWidth - spec.horizontalIndent; + widgetX= columnX + spec.horizontalIndent; + } else { + widgetW= childExtent.x; + } + + // Calculate the y and height values for the widget. + vAlign= spec.verticalAlignment; + widgetY= rowY; + if (vAlign == spec.CENTER) { + widgetY= widgetY + (spannedHeight / 2) - (childExtent.y / 2); + } else if (vAlign == spec.END) { + widgetY= widgetY + spannedHeight - childExtent.y; + } else { + widgetY= widgetY; + } + if (vAlign == spec.FILL) { + widgetH= spannedHeight; + widgetY= rowY; + } else { + widgetH= childExtent.y; + } + // Place the widget. + child.setBounds(widgetX, widgetY, widgetW, widgetH); + } + // Update the starting x value. + columnX= columnX + columnWidths[c] + horizontalSpacing; + } + // Update the starting y value and since we're starting a new row, reset the starting x value. + rowY= rowY + rowHeights[r] + verticalSpacing; + columnX= marginWidth + composite.getBorderWidth() + composite.getClientArea().x; + } + //System.out.println("end layout " + id); + } + public MGridLayout() { + super(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICCompletionContributor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICCompletionContributor.java new file mode 100644 index 00000000000..00ff6c1365e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICCompletionContributor.java @@ -0,0 +1,25 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +public interface ICCompletionContributor { + + /** + * Initialize the completion contributor class + */ + void initialize(); + + /** + * get the matching function of a given name + */ + IFunctionSummary getFunctionInfo(String name); + + /** + * Get array of matching functions starting with this prefix + */ + IFunctionSummary[] getMatchingFunctions(String prefix); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICDTConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICDTConstants.java new file mode 100644 index 00000000000..69e4a6aa344 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICDTConstants.java @@ -0,0 +1,25 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +public interface ICDTConstants +{ + // CDT Extension Points + public static final String EP_TEXT_HOVERS = "textHovers"; + public static final String EP_EDITOR_ACTIONS = "editorActions"; + public static final String EP_EDITOR_RULER_ACTIONS = "editorRulerActions"; + + // Persistance tags. + public static final String TAG_TEXT_HOVER = "textHover"; + public static final String TAG_ACTION = "action"; + + // Atributes + public static final String ATT_CLASS = "class"; + public static final String ATT_ID = "id"; + public static final String ATT_NAME = "name"; + public static final String ATT_PERSPECTIVE = "perspective"; +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorContextMenuAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorContextMenuAction.java new file mode 100644 index 00000000000..2d0bddaac4b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorContextMenuAction.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.texteditor.ITextEditor; + +public interface ICEditorContextMenuAction extends IAction +{ + void init( ITextEditor textEditor ); + String getMenuPath(); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorRulerAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorRulerAction.java new file mode 100644 index 00000000000..b397118b62c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/ICEditorRulerAction.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.ui.texteditor.ITextEditor; + +public interface ICEditorRulerAction extends IAction +{ + void init( IVerticalRuler ruler, ITextEditor textEditor ); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IFunctionSummary.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IFunctionSummary.java new file mode 100644 index 00000000000..b5adc426bfd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IFunctionSummary.java @@ -0,0 +1,35 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +public interface IFunctionSummary { + + /** + * Get the name of the function + */ + public String getName(); + + /** + * Get the function summary + */ + public String getSummary(); + + /** + * Get the function prototype + */ + public String getPrototype(); + + /** + * Get the function synopsis + */ + public String getSynopsis(); + + /** + * Get headers required by this function + */ + public IRequiredInclude[] getIncludes(); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IRequiredInclude.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IRequiredInclude.java new file mode 100644 index 00000000000..d360c55f0f5 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IRequiredInclude.java @@ -0,0 +1,26 @@ +package org.eclipse.cdt.ui; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +public interface IRequiredInclude { + + /** + * Returns the name that has been imported. + * For an on-demand import, this includes the trailing ".*". + * For example, for the statement "import java.util.*", + * this returns "java.util.*". + * For the statement "import java.util.Hashtable", + * this returns "java.util.Hashtable". + */ + String getIncludeName(); + + /** + * Returns whether the include is to search on "standard places" like /usr/include first . + * An include is standard if it starts with "\<". + */ + boolean isStandard(); +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CCProjectWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CCProjectWizard.java new file mode 100644 index 00000000000..6502dce329b --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CCProjectWizard.java @@ -0,0 +1,69 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.cdt.core.CCProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; + + +/** + * C Project wizard that creates a new project resource in + */ +public abstract class CCProjectWizard extends CProjectWizard { + + private static final String OP_ERROR= "CCProjectWizard.op_error"; //$NON-NLS-1$ + private static final String OP_DESC= "CCProjectWizard.op_description"; //$NON-NLS-1$ + + private static final String PREFIX= "CCProjectWizard"; //$NON-NLS-1$ + private static final String WZ_TITLE= "CCProjectWizard.title"; //$NON-NLS-1$ + private static final String WZ_DESC= "CCProjectWizard.description"; //$NON-NLS-1$ + + private static final String WINDOW_TITLE = "CCProjectWizard.windowTitle"; //$NON-NLS-1$ + + private String wz_title; + private String wz_desc; + private String op_error; + + public CCProjectWizard() { + super(); + setDialogSettings(CPlugin.getDefault().getDialogSettings()); + wz_title = CPlugin.getResourceString(WZ_TITLE); + wz_desc = CPlugin.getResourceString(WZ_DESC); + op_error = CPlugin.getResourceString(OP_ERROR); + } + + public CCProjectWizard(String title, String description) { + super(); + setDialogSettings(CPlugin.getDefault().getDialogSettings()); + wz_title = title; + wz_desc = description; + op_error = CPlugin.getResourceString(OP_ERROR); + } + + + public CCProjectWizard(String title, String description, String error) { + super(); + setDialogSettings(CPlugin.getDefault().getDialogSettings()); + wz_title = title; + wz_desc = description; + op_error = error; + } + + + protected void doRun(IProgressMonitor monitor) { + super.doRun(monitor); + // Add C++ Nature. + if (newProject != null) { + try { + CCProjectNature.addCCNature(newProject, monitor); + } catch (CoreException e) { + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizard.java new file mode 100644 index 00000000000..f69c3664778 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizard.java @@ -0,0 +1,333 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation; +import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; +import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; + +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.utils.ui.swt.IValidation; + + +/** + * C Project wizard that creates a new project resource in + */ +public abstract class CProjectWizard extends BasicNewResourceWizard implements IExecutableExtension { + + private static final String OP_ERROR= "CProjectWizard.op_error"; //$NON-NLS-1$ + private static final String OP_DESC= "CProjectWizard.op_description"; //$NON-NLS-1$ + + private static final String PREFIX= "CProjectWizard"; //$NON-NLS-1$ + private static final String WZ_TITLE= "CProjectWizard.title"; //$NON-NLS-1$ + private static final String WZ_DESC= "CProjectWizard.description"; //$NON-NLS-1$ + + private static final String WINDOW_TITLE = "CProjectWizard.windowTitle"; //$NON-NLS-1$ + + private String wz_title; + private String wz_desc; + private String op_error; + + protected IConfigurationElement fConfigElement; + protected CProjectWizardPage fMainPage; + protected TabFolderPage fTabFolderPage; + protected IProject newProject; + + List tabItemsList = new ArrayList(); + + public CProjectWizard() { + this(CPlugin.getResourceString(WZ_TITLE), CPlugin.getResourceString(WZ_DESC), + CPlugin.getResourceString(OP_ERROR)); + } + + public CProjectWizard(String title, String description) { + this(title, description, CPlugin.getResourceString(OP_ERROR)); + } + + public CProjectWizard(String title, String description, String error) { + super(); + setDialogSettings(CPlugin.getDefault().getDialogSettings()); + setNeedsProgressMonitor(true); + wz_title = title; + wz_desc = description; + op_error = error; + } + + /** + * @see Wizard#createPages + */ + public void addPages() { + fMainPage= new CProjectWizardPage(CPlugin.getResourceString(PREFIX)); + fMainPage.setTitle(wz_title); + fMainPage.setDescription(wz_desc); + addPage(fMainPage); + + fTabFolderPage = new TabFolderPage(this); + addPage(fTabFolderPage); + } + + public void addTabItem(IWizardTab item) { + tabItemsList.add(item); + } + + public IWizardTab [] getTabItems() { + return (IWizardTab[])tabItemsList.toArray(new IWizardTab[0]); + } + + public abstract void addTabItems(TabFolder tabFolder); + + protected abstract void doRunPrologue(IProgressMonitor monitor); + + protected abstract void doRunEpilogue(IProgressMonitor monitor); + + /** + * Gets the project location path from the main page + * Overwrite this method if you do not have a main page + */ + protected IPath getLocationPath() { + return fMainPage.getLocationPath(); + } + + /** + * Gets the project handle from the main page. + * Overwrite this method if you do not have a main page + */ + + protected IProject getProjectHandle() { + return fMainPage.getProjectHandle(); + } + + /** + * Returns the C project handle corresponding to the project defined in + * in the main page. + * + * @returns the C project + */ + protected IProject getNewProject() { + return newProject; + } + + protected IResource getSelectedResource() { + return getNewProject(); + } + + protected IValidation getValidation() { + return fTabFolderPage; + } + + /** + * @see Wizard#performFinish + */ + public boolean performFinish() { + if (!invokeRunnable(getRunnable())) { + return false; + } + BasicNewProjectResourceWizard.updatePerspective(fConfigElement); + IResource resource = getSelectedResource(); + selectAndReveal(resource); + if (resource != null && resource.getType() == IResource.FILE) { + IFile file = (IFile)resource; + // Open editor on new file. + IWorkbenchWindow dw = getWorkbench().getActiveWorkbenchWindow(); + if (dw != null) { + try { + IWorkbenchPage page = dw.getActivePage(); + if (page != null) + page.openEditor(file); + } catch (PartInitException e) { + MessageDialog.openError(dw.getShell(), + CPlugin.getResourceString(OP_ERROR), e.getMessage()); + } + } + } + return true; + } + + /** + * Stores the configuration element for the wizard. The config element will be used + * in performFinish to set the result perspective. + * + * @see IExecutableExtension#setInitializationData + */ + public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) { + fConfigElement= cfig; + } + + /* + * Reimplemented method from superclass + */ + protected void initializeDefaultPageImageDescriptor() { + setDefaultPageImageDescriptor(CPluginImages.DESC_WIZABAN_NEW_PROJ); + } + + /* (non-Javadoc) + * Method declared on IWorkbenchWizard. + */ + public void init(IWorkbench workbench, IStructuredSelection currentSelection) { + super.init(workbench, currentSelection); + setWindowTitle(CPlugin.getResourceString(WINDOW_TITLE)); + } + + public IRunnableWithProgress getRunnable() { + return new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + if (monitor == null) { + monitor= new NullProgressMonitor(); + } + monitor.beginTask(CPlugin.getResourceString(OP_DESC), 3); + + doRunPrologue(new SubProgressMonitor(monitor, 1)); + doRun(new SubProgressMonitor(monitor, 1)); + doRunEpilogue(new SubProgressMonitor(monitor, 1)); + + monitor.done(); + } + }; + } + + /** + * Utility method: call a runnable in a WorkbenchModifyDelegatingOperation + */ + protected boolean invokeRunnable(IRunnableWithProgress runnable) { + IRunnableWithProgress op= new WorkspaceModifyDelegatingOperation(runnable); + try { + getContainer().run(false, true, op); + } catch (InvocationTargetException e) { + Shell shell= getShell(); + String title= CPlugin.getResourceString(OP_ERROR + ".title"); //$NON-NLS-1$ + String message= CPlugin.getResourceString(OP_ERROR + ".message"); //$NON-NLS-1$ + + Throwable th= e.getTargetException(); + if (th instanceof CoreException) { + IStatus status= ((CoreException)th).getStatus(); + if (status != null) { + ErrorDialog.openError(shell, title, message, status); + CPlugin.log(status); + return false; + } + } + MessageDialog.openError(shell, title, message); + CPlugin.log(th); + return false; + } catch (InterruptedException e) { + return false; + } + return true; + } + + protected void doRun(IProgressMonitor monitor) { + createNewProject(monitor); + } + + /** + * Creates a new project resource with the selected name. + *

+ * In normal usage, this method is invoked after the user has pressed Finish on + * the wizard; the enablement of the Finish button implies that all controls + * on the pages currently contain valid values. + *

+ *

+ * Note that this wizard caches the new project once it has been successfully + * created; subsequent invocations of this method will answer the same + * project resource without attempting to create it again. + *

+ * + * @return the created project resource, or null if the project + * was not created + */ + protected IProject createNewProject(IProgressMonitor monitor) { + + if (newProject != null) + return newProject; + + // get a project handle + IProject newProjectHandle = getProjectHandle(); + + // get a project descriptor + IPath defaultPath = Platform.getLocation(); + IPath newPath = getLocationPath(); + if (defaultPath.equals(newPath)) + newPath = null; + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName()); + description.setLocation(newPath); + + try { + newProject = createProject(description, newProjectHandle, monitor); + } catch (CoreException e) { + return null; + } catch (OperationCanceledException e) { + return null; + } + return newProject; + } + + /** + * Creates a project resource given the project handle and description. + * + * @param description the project description to create a project resource for + * @param projectHandle the project handle to create a project resource for + * @param monitor the progress monitor to show visual progress with + * + * @exception CoreException if the operation fails + * @exception OperationCanceledException if the operation is canceled + */ + private IProject createProject(IProjectDescription description, IProject projectHandle, + IProgressMonitor monitor) throws CoreException, OperationCanceledException { + try { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Creating C Project", 3);//$NON-NLS-1$ + + projectHandle.create(description, new SubProgressMonitor(monitor, 1)); + + if (monitor.isCanceled()) + throw new OperationCanceledException(); + + // Open first. + projectHandle.open(new SubProgressMonitor(monitor, 1)); + // Add C Nature. + CProjectNature.addCNature(projectHandle, new SubProgressMonitor(monitor, 1)); + + } finally { + //monitor.done(); + } + return projectHandle; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizardPage.java new file mode 100644 index 00000000000..8a10b1d3942 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/CProjectWizardPage.java @@ -0,0 +1,344 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.File; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.help.DialogPageContextComputer; +import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.internal.IHelpContextIds; + +import org.eclipse.cdt.internal.ui.CPlugin; + +/** + * Standard main page for a wizard that is creates a project resource. + *

+ * This page may be used by clients as-is; it may be also be subclassed to suit. + *

+ *

+ * Example useage: + *

+ * mainPage = new CProjectWizardPage("basicCProjectPage");
+ * mainPage.setTitle("Project");
+ * mainPage.setDescription("Create a new project resource.");
+ * 
+ *

+ */ +public class CProjectWizardPage extends WizardPage { + + private boolean useDefaults = true; + + // initial value stores + private String initialProjectFieldValue; + private IPath initialLocationFieldValue; + + // widgets + private Text projectNameField; + private Text locationPathField; + private Label locationLabel; + private Button browseButton; + + private Listener nameModifyListener = new Listener() { + public void handleEvent(Event e) { + setLocationForSelection(); + setPageComplete(validatePage()); + } + }; + + private Listener locationModifyListener = new Listener() { + public void handleEvent(Event e) { + setPageComplete(validatePage()); + } + }; + + // constants + private static final int SIZING_TEXT_FIELD_WIDTH = 250; + private static final int SIZING_INDENTATION_WIDTH = 10; + + /** (non-Javadoc) + * Method declared on IDialogPage. + */ + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + + WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, IHelpContextIds.NEW_PROJECT_WIZARD_PAGE)); + + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + createProjectNameGroup(composite); + createProjectLocationGroup(composite); + projectNameField.setFocus(); + validatePage(); + // Show description on opening + setErrorMessage(null); + setMessage(null); + setControl(composite); + } + + /** + * Creates the project location specification controls. + * + * @param parent the parent composite + */ + private final void createProjectLocationGroup(Composite parent) { + + // project specification group + Composite projectGroup = new Composite(parent,SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + projectGroup.setLayout(layout); + projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Button useDefaultsButton = new Button(projectGroup, SWT.CHECK | SWT.RIGHT); + useDefaultsButton.setText(CPlugin.getResourceString("CProjectWizardPage.useDefaultLabel")); //$NON-NLS-1$ + useDefaultsButton.setSelection(this.useDefaults); + + GridData buttonData = new GridData(); + buttonData.horizontalSpan = 3; + useDefaultsButton.setLayoutData(buttonData); + + createUserSpecifiedProjectLocationGroup(projectGroup,!this.useDefaults); + + SelectionListener listener = new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + useDefaults = useDefaultsButton.getSelection(); + browseButton.setEnabled(!useDefaults); + locationPathField.setEnabled(!useDefaults); + locationLabel.setEnabled(!useDefaults); + setLocationForSelection(); + if (!useDefaults) + locationPathField.setText(""); //$NON-NLS-1$ + } + }; + useDefaultsButton.addSelectionListener(listener); + } + + /** + * Creates the project name specification controls. + * + * @param parent the parent composite + */ + private final void createProjectNameGroup(Composite parent) { + // project specification group + Composite projectGroup = new Composite(parent,SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + projectGroup.setLayout(layout); + projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // new project label + Label projectLabel = new Label(projectGroup,SWT.NONE); + projectLabel.setText(CPlugin.getResourceString("CProjectWizardPage.nameLabel")); //$NON-NLS-1$ + + // new project name entry field + projectNameField = new Text(projectGroup, SWT.BORDER); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.widthHint = SIZING_TEXT_FIELD_WIDTH; + projectNameField.setLayoutData(data); + + // Set the initial value first before listener + // to avoid handling an event during the creation. + if (initialProjectFieldValue != null) + projectNameField.setText(initialProjectFieldValue); + projectNameField.addListener(SWT.Modify, nameModifyListener); + projectNameField.setVisible(true); + } + + /** + * Creates the project location specification controls. + * + * @param projectGroup the parent composite + * @param boolean - the initial enabled state of the widgets created + */ + private void createUserSpecifiedProjectLocationGroup(Composite projectGroup, boolean enabled) { + + // location label + locationLabel = new Label(projectGroup,SWT.NONE); + locationLabel.setText(CPlugin.getResourceString("CProjectWizardPage.locationLabel")); //$NON-NLS-1$ + locationLabel.setEnabled(enabled); + + // project location entry field + locationPathField = new Text(projectGroup, SWT.BORDER); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.widthHint = SIZING_TEXT_FIELD_WIDTH; + locationPathField.setLayoutData(data); + locationPathField.setEnabled(enabled); + + // browse button + browseButton = new Button(projectGroup, SWT.PUSH); + browseButton.setText(CPlugin.getResourceString("CProjectWizardPage.browseLabel")); //$NON-NLS-1$ + browseButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + handleLocationBrowseButtonPressed(); + } + }); + + browseButton.setEnabled(enabled); + + // Set the initial value first before listener + // to avoid handling an event during the creation. + if (initialLocationFieldValue != null) + locationPathField.setText(initialLocationFieldValue.toOSString()); + locationPathField.addListener(SWT.Modify, locationModifyListener); + } + + /** + * Returns the current project location path as entered by + * the user, or its anticipated initial value. + * + * @return the project location path, its anticipated initial value, or null + * if no project location path is known + */ + public IPath getLocationPath() { + if (useDefaults) + return initialLocationFieldValue; + + return new Path(locationPathField.getText()); + } + + /** + * Creates a project resource handle for the current project name field value. + *

+ * This method does not create the project resource; this is the responsibility + * of IProject::create invoked by the new project resource wizard. + *

+ * + * @return the new project resource handle + */ + public IProject getProjectHandle() { + return ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName()); + } + + /** + * Returns the current project name as entered by the user, or its anticipated + * initial value. + * + * @return the project name, its anticipated initial value, or null + * if no project name is known + */ + public String getProjectName() { + if (projectNameField == null) + return initialProjectFieldValue; + + return projectNameField.getText(); + } + + /** + * Open an appropriate directory browser + */ + private void handleLocationBrowseButtonPressed() { + DirectoryDialog dialog = new DirectoryDialog(locationPathField.getShell()); + dialog.setMessage(CPlugin.getResourceString("CProjectWizardPage.directoryLabel")); //$NON-NLS-1$ + + String dirName = locationPathField.getText(); + if (!dirName.equals("")) {//$NON-NLS-1$ + File path = new File(dirName); + if (path.exists()) + dialog.setFilterPath(dirName); + } + + String selectedDirectory = dialog.open(); + if (selectedDirectory != null) + locationPathField.setText(selectedDirectory); + } + + /** + * Creates a new project creation wizard page. + * + * @param pageName the name of this page + */ + public CProjectWizardPage(String pageName) { + super(pageName); + setPageComplete(false); + this.initialLocationFieldValue = Platform.getLocation(); + } + + /** + * Set the location to the default location if we are set to useDefaults. + */ + private void setLocationForSelection() { + if (useDefaults) { + IPath defaultPath = Platform.getLocation().append(projectNameField.getText()); + locationPathField.setText(defaultPath.toOSString()); + } + } + + /** + * Returns whether this page's controls currently all contain valid + * values. + * + * @return true if all controls are valid, and + * false if at least one is invalid + */ + private boolean validatePage() { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + + String projectFieldContents = projectNameField.getText(); + if (projectFieldContents.equals("")) { //$NON-NLS-1$ + setErrorMessage(null); + setMessage(CPlugin.getResourceString("CProjectWizardPage.projectNameEmpty")); //$NON-NLS-1$ + return false; + } + + if (projectFieldContents.indexOf(' ') != -1) { + setErrorMessage(CPlugin.getResourceString("CProjectWizardPage.projectContainsSpace")); //$NON-NLS-1$ + return false; + } + + IStatus nameStatus = + workspace.validateName(projectFieldContents, IResource.PROJECT); + if (!nameStatus.isOK()) { + setErrorMessage(nameStatus.getMessage()); + return false; + } + + String locationFieldContents = locationPathField.getText(); + + if (!locationFieldContents.equals("")) {//$NON-NLS-1$ + IPath path = new Path("");//$NON-NLS-1$ + if (!path.isValidPath(locationFieldContents)) { + setErrorMessage(CPlugin.getResourceString("CProjectWizardPage.locationError")); //$NON-NLS-1$ + return false; + } + if (!useDefaults && Platform.getLocation().isPrefixOf(new Path(locationFieldContents))) { + setErrorMessage(CPlugin.getResourceString("CProjectWizardPage.defaultLocationError")); //$NON-NLS-1$ + return false; + } + } + + if (getProjectHandle().exists()) { + setErrorMessage(CPlugin.getResourceString("CProjectWizardPage.projectExistsMessage")); //$NON-NLS-1$ + return false; + } + + setErrorMessage(null); + setMessage(null); + return true; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IWizardTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IWizardTab.java new file mode 100644 index 00000000000..7b4d9bbb2ba --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/IWizardTab.java @@ -0,0 +1,26 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; + +public interface IWizardTab { + + public String getLabel(); + + public Image getImage(); + + public Composite getControl(Composite parent); + + public boolean isValid(); + + public void setVisible(boolean visible); + + public void doRun(IProject project, IProgressMonitor monitor); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/ReferenceBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/ReferenceBlock.java new file mode 100644 index 00000000000..d40c887839a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/ReferenceBlock.java @@ -0,0 +1,187 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.model.WorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.utils.ui.swt.IValidation; + +public class ReferenceBlock implements IWizardTab { + + private static final String PREFIX = "ReferenceBlock"; // $NON-NLS-1$ + private static final String LABEL = PREFIX + ".label"; // $NON-NLS-1$ + private static final String DESC = PREFIX + ".desc"; // $NON-NLS-1$ + + private CheckboxTableViewer referenceProjectsViewer; + private static final int PROJECT_LIST_MULTIPLIER = 15; + + IProject project; + IValidation page; + + /** (non-Javadoc) + * Method declared on IDialogPage. + */ + public Composite getControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label label = new Label(composite, SWT.LEFT); + label.setText(CPlugin.getResourceString(DESC)); + GridData lbldata = new GridData(GridData.FILL_HORIZONTAL); + lbldata.horizontalSpan = 1; + label.setLayoutData(lbldata); + + referenceProjectsViewer = new CheckboxTableViewer(composite, SWT.BORDER); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + + data.heightHint = getDefaultFontHeight( referenceProjectsViewer.getTable(), + PROJECT_LIST_MULTIPLIER); + referenceProjectsViewer.getTable().setLayoutData(data); + referenceProjectsViewer.setLabelProvider(new WorkbenchLabelProvider()); + referenceProjectsViewer.setContentProvider(getContentProvider()); + referenceProjectsViewer.setInput(ResourcesPlugin.getWorkspace()); + + initializeValues(); + + return composite; + } + + public Image getImage() { + return CPluginImages.get(CPluginImages.IMG_OBJS_PROJECT); + } + + public String getLabel() { + return CPlugin.getResourceString(LABEL); + } + + /** + * Returns a content provider for the reference project + * viewer. It will return all projects in the workspace. + * + * @return the content provider + */ + protected IStructuredContentProvider getContentProvider() { + return new WorkbenchContentProvider() { + public Object[] getChildren(Object element) { + if (!(element instanceof IWorkspace)) + return new Object[0]; + ArrayList aList = new ArrayList(15); + IProject[] projects = ((IWorkspace)element).getRoot().getProjects(); + for (int i = 0; i < projects.length; i++) { + if (CoreModel.hasCNature(projects[i])) { + // Do not show the actual project being look at + if (project != null && project.equals(projects[i])) { + continue; + } + aList.add(projects[i]); + } + } + return aList.toArray(); + } + }; + } + + /** + * Get the default widget height for the supplied control. + * @return int + * @param control - the control being queried about fonts + * @param lines - the number of lines to be shown on the table. + */ + private static int getDefaultFontHeight(Control control, int lines) { + FontData[] viewerFontData = control.getFont().getFontData(); + int fontHeight = 10; + + //If we have no font data use our guess + if (viewerFontData.length > 0) + fontHeight = viewerFontData[0].getHeight(); + return lines * fontHeight; + } + + protected void initializeValues () { + if (project != null) { + try { + IProject[] referenced = project.getReferencedProjects(); + referenceProjectsViewer.setCheckedElements(referenced); + } catch (CoreException e) { + } + } + } + + /** + * Returns the referenced projects selected by the user. + * + * @return the referenced projects + */ + public IProject[] getReferencedProjects() { + Object[] elements = referenceProjectsViewer.getCheckedElements(); + IProject[] projects = new IProject[elements.length]; + System.arraycopy(elements, 0, projects, 0, elements.length); + return projects; + } + + public boolean isValid() { + return true; + } + + public void setVisible(boolean visible) { + } + + public void doRun(IProject project, IProgressMonitor monitor) { + IProject[] refProjects = getReferencedProjects(); + if (refProjects != null) { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Reference Projects", 1); + try { + IProjectDescription description = project.getDescription(); + description.setReferencedProjects(refProjects); + project.setDescription(description, new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + } + } + } + + /** + * + */ + public ReferenceBlock(IValidation page) { + this(page, null); + } + + public ReferenceBlock(IValidation page, IProject project) { + super(); + this.page = page; + this.project = project; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/SettingsBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/SettingsBlock.java new file mode 100644 index 00000000000..a79976e4d26 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/SettingsBlock.java @@ -0,0 +1,244 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; +import org.eclipse.cdt.utils.ui.swt.IValidation; +import org.eclipse.cdt.utils.ui.controls.ControlFactory; +import org.eclipse.cdt.utils.ui.controls.RadioButtonsArea; + + +public class SettingsBlock implements IWizardTab { + + private static final String PREFIX = "SettingsBlock"; //$NON-NLS-1$ + private static final String LABEL = PREFIX + ".label"; //$NON-NLS-1$ + private static final String KEEP_GOING = PREFIX + ".keepOnGoing"; //$NON-NLS-1$ + private static final String STOP_ERROR = PREFIX + ".stopOnError"; //$NON-NLS-1$ + private static final String MAKE_OPTION = PREFIX + ".makeOption.label"; + //$NON-NLS-1$ + private static final String MAKE_USE_DEFAULT = + PREFIX + ".makeOption.use_default"; + //$NON-NLS-1$ + private static final String MAKE_BUILD_CMD = PREFIX + ".makeOption.build_cmd"; + //$NON-NLS-1$ + + private static final String KEEP_ARG = "keep"; //$NON-NLS-1$ + private static final String STOP_ARG = "stop"; //$NON-NLS-1$ + + private RadioButtonsArea radioButtons; + private Button defButton; + private Text cmdText; + + private boolean stopOnError; + private boolean useDefaultBuildCmd; + private boolean defaultSelectionMade = false; + private String buildCmd; + IValidation page; + + public SettingsBlock(IValidation valid) { + this(valid, null); + } + + public SettingsBlock(IValidation valid, IProject project) { + if (project != null) { + try { + CProjectNature nature = + (CProjectNature) project.getNature(CProjectNature.C_NATURE_ID); + if (nature != null) { + stopOnError = nature.isStopOnError(); + useDefaultBuildCmd = nature.isDefaultBuildCmd(); + if (!useDefaultBuildCmd) { + buildCmd = nature.getBuildCommand().toOSString(); + buildCmd += " " + nature.getFullBuildArguments(); + } + } + } + catch (CoreException e) { + } + } + else { + // FIXME: Should use the default settings + stopOnError = false; + useDefaultBuildCmd = true; + } + page = valid; + } + + public String getLabel() { + return CPlugin.getResourceString(LABEL); + } + + public Image getImage() { + return null; + } + + public Composite getControl(Composite parent) { + Composite composite = ControlFactory.createComposite(parent, 1); + + String[][] radios = + new String[][] { { CPlugin.getResourceString(STOP_ERROR), STOP_ARG }, { + CPlugin.getResourceString(KEEP_GOING), KEEP_ARG } + }; + radioButtons = + new RadioButtonsArea(composite, CPlugin.getResourceString(LABEL), 1, radios); + + Group mgroup = + ControlFactory.createGroup( + composite, + CPlugin.getResourceString(MAKE_OPTION), + 1); + defButton = + ControlFactory.createCheckBox( + mgroup, + CPlugin.getResourceString(MAKE_USE_DEFAULT)); + defButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (defButton.getSelection() == true) { + cmdText.setEnabled(false); + radioButtons.setEnabled(true); + if (null != page) + page.setComplete(isValid()); + + } + else { + cmdText.setEnabled(true); + radioButtons.setEnabled(false); + if (null != page) + page.setComplete(isValid()); + } + } + }); + Composite cmdComp = new Composite(mgroup, SWT.NULL); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.makeColumnsEqualWidth = false; + layout.marginWidth = 0; + layout.horizontalSpacing = 0; + cmdComp.setLayout(layout); + cmdComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + Label label = + ControlFactory.createLabel(cmdComp, CPlugin.getResourceString(MAKE_BUILD_CMD)); + ((GridData) (label.getLayoutData())).horizontalAlignment = GridData.BEGINNING; + ((GridData) (label.getLayoutData())).grabExcessHorizontalSpace = false; + cmdText = ControlFactory.createTextField(cmdComp, SWT.SINGLE | SWT.BORDER); + ((GridData) (cmdText.getLayoutData())).horizontalAlignment = GridData.FILL; + ((GridData) (cmdText.getLayoutData())).grabExcessHorizontalSpace = true; + cmdText.addListener(SWT.Modify, new Listener() { + public void handleEvent(Event e) { + page.setComplete(isValid()); + } + }); + if ( buildCmd != null ) + cmdText.setText(buildCmd); + if (useDefaultBuildCmd) { + cmdText.setEnabled(false); + } else { + radioButtons.setEnabled(false); + } + return composite; + } + + public boolean isValid() { + if (defButton.getSelection() != true) { + String cmd = getBuildLine(); + if (cmd == null || cmd.length() == 0) { + return false; + } + } + return true; + } + + public void setVisible(boolean visible) { + if ( !defaultSelectionMade ) { + if (stopOnError) + radioButtons.setSelectValue(STOP_ARG); + else + radioButtons.setSelectValue(KEEP_ARG); + defButton.setSelection(useDefaultBuildCmd); + defaultSelectionMade = true; + } + } + + public void doRun(IProject project, IProgressMonitor monitor) { + try { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Settings", 1); + CProjectNature nature = + (CProjectNature) project.getNature(CProjectNature.C_NATURE_ID); + if (nature != null) { + nature.setStopOnError(isStopOnError()); + nature.setBuildCommandOverride(useDefaultBuildCmd()); + if (!useDefaultBuildCmd()) { + String bldLine = getBuildLine(); + int start = bldLine.indexOf(' '); + IPath path; + if ( start == -1 ) { + path = new Path(bldLine); + } else { + path = new Path(bldLine.substring(0, start)); + } + nature.setBuildCommand(path, new SubProgressMonitor(monitor, 50)); + String args = ""; + if ( start != -1 ) { + args = bldLine.substring(start + 1); + } + nature.setFullBuildArguments(args, new SubProgressMonitor(monitor, 50)); + } + } + } + catch (CoreException e) { + } + } + + private boolean isStopOnError() { + if ( defaultSelectionMade ) { + if (radioButtons != null) + return radioButtons.getSelectedValue().equals(STOP_ARG); + } + return stopOnError; + } + + private boolean useDefaultBuildCmd() { + if ( defaultSelectionMade ) { + if (defButton != null) + return defButton.getSelection(); + } + return useDefaultBuildCmd; + } + + private String getBuildLine() { + if (cmdText != null) { + String cmd = cmdText.getText(); + if (cmd != null) + return cmd.trim(); + } + return null; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCCWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCCWizard.java new file mode 100644 index 00000000000..503f9afa62d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCCWizard.java @@ -0,0 +1,54 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.swt.widgets.TabFolder; + +import org.eclipse.cdt.core.CCProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; + + +/** + */ +public class StdCCWizard extends StdMakeProjectWizard { + + private static final String WZ_TITLE = "StdCCWizard.title"; + private static final String WZ_DESC = "StdCCWizard.description"; + private static final String SETTINGS_TITLE= "StdCCWizardSettings.title"; //$NON-NLS-1$ + private static final String SETTINGS_DESC= "StdCCWizardSettings.description"; //$NON-NLS-1$ + + public StdCCWizard() { + this(CPlugin.getResourceString(WZ_TITLE), CPlugin.getResourceString(WZ_DESC)); + } + + public StdCCWizard(String title, String desc) { + super(title, desc); + } + + public void addTabItems(TabFolder folder) { + super.addTabItems(folder); + fTabFolderPage.setTitle(CPlugin.getResourceString(SETTINGS_TITLE)); + fTabFolderPage.setDescription(CPlugin.getResourceString(SETTINGS_DESC)); + } + protected void doRun(IProgressMonitor monitor) { + super.doRun(monitor); + // Add C++ Nature. + if (newProject != null) { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Standard C++ Make", 1); + try { + CCProjectNature.addCCNature(newProject, new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCWizard.java new file mode 100644 index 00000000000..6b24657d6f1 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdCWizard.java @@ -0,0 +1,34 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.swt.widgets.TabFolder; + +import org.eclipse.cdt.internal.ui.CPlugin; + +/** + */ +public class StdCWizard extends StdMakeProjectWizard { + + private static final String WZ_TITLE = "StdCWizard.title"; + private static final String WZ_DESC = "StdCWizard.description"; + private static final String SETTINGS_TITLE= "StdCWizardSettings.title"; //$NON-NLS-1$ + private static final String SETTINGS_DESC= "StdCWizardSettings.description"; //$NON-NLS-1$ + + public StdCWizard() { + this(CPlugin.getResourceString(WZ_TITLE), CPlugin.getResourceString(WZ_DESC)); + } + + public StdCWizard(String title, String desc) { + super(title, desc); + } + + public void addTabItems(TabFolder folder) { + super.addTabItems(folder); + fTabFolderPage.setTitle(CPlugin.getResourceString(SETTINGS_TITLE)); + fTabFolderPage.setDescription(CPlugin.getResourceString(SETTINGS_DESC)); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdMakeProjectWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdMakeProjectWizard.java new file mode 100644 index 00000000000..aae5169e880 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/StdMakeProjectWizard.java @@ -0,0 +1,95 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; + +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.internal.ui.CPlugin; + + +/** + */ +public abstract class StdMakeProjectWizard extends CProjectWizard { + + private static final String OP_ERROR= "StdMakeProjectWizard.op_error"; + private static final String WZ_TITLE= "StdMakeProjectWizard.title"; + private static final String WZ_DESC= "StdMakeProjectWizard.description"; + private static final String SETTINGS_TITLE= "StdMakeWizardSettings.title"; //$NON-NLS-1$ + private static final String SETTINGS_DESC= "StdMakeWizardSettings.description"; //$NON-NLS-1$ + + private ReferenceBlock referenceBlock; + private SettingsBlock settingsBlock; + + public StdMakeProjectWizard() { + this(CPlugin.getResourceString(WZ_TITLE), CPlugin.getResourceString(WZ_DESC)); + } + + public StdMakeProjectWizard(String title, String desc) { + super(title, desc); + } + + public void addTabItems(TabFolder folder) { + fTabFolderPage.setTitle(CPlugin.getResourceString(SETTINGS_TITLE)); + fTabFolderPage.setDescription(CPlugin.getResourceString(SETTINGS_DESC)); + + referenceBlock = new ReferenceBlock(getValidation()); + TabItem item = new TabItem(folder, SWT.NONE); + item.setText(referenceBlock.getLabel()); + Image img = referenceBlock.getImage(); + if (img != null) + item.setImage(img); + item.setData(referenceBlock); + item.setControl(referenceBlock.getControl(folder)); + addTabItem(referenceBlock); + + settingsBlock = new SettingsBlock(getValidation()); + TabItem item2 = new TabItem(folder, SWT.NONE); + item2.setText(settingsBlock.getLabel()); + Image img2 = settingsBlock.getImage(); + if (img2 != null) + item2.setImage(img2); + item2.setData(settingsBlock); + item2.setControl(settingsBlock.getControl(folder)); + addTabItem(settingsBlock); + } + + protected void doRunPrologue(IProgressMonitor monitor) { + } + + protected void doRunEpilogue(IProgressMonitor monitor) { + } + + protected void doRun(IProgressMonitor monitor) { + super.doRun(monitor); + if (newProject != null) { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask("Standard Make", 3); + try { + // Update the referenced project if provided. + if (referenceBlock != null) { + referenceBlock.doRun(newProject, new SubProgressMonitor(monitor, 1)); + } + // Update the settings. + if (settingsBlock != null) { + settingsBlock.doRun(newProject, new SubProgressMonitor(monitor, 1)); + } + // Set the Default C Builder. + CProjectNature.addCBuildSpec(newProject, new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + } + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/TabFolderPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/TabFolderPage.java new file mode 100644 index 00000000000..db62ea3dc9d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/TabFolderPage.java @@ -0,0 +1,104 @@ +package org.eclipse.cdt.ui.wizards; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TabFolder; + +import org.eclipse.cdt.internal.ui.wizards.swt.MGridData; +import org.eclipse.cdt.internal.ui.wizards.swt.MGridLayout; +import org.eclipse.cdt.utils.ui.swt.IValidation; +import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; + +/** + * Standard main page for a wizard that is creates a project resource. + *

+ * This page may be used by clients as-is; it may be also be subclassed to suit. + *

+ *

+ * Example useage: + *

+ * mainPage = new CProjectWizardPage("basicCProjectPage");
+ * mainPage.setTitle("Project");
+ * mainPage.setDescription("Create a new project resource.");
+ * 
+ *

+ */ +public class TabFolderPage extends WizardPage implements IValidation { + + private static final String WZ_TITLE= "TabFolderPage.title"; + private static final String WZ_DESC= "TabFolderPage.desc"; + + protected TabFolder tabFolder; + protected CProjectWizard wizard; + + /** (non-Javadoc) + * Method declared on IDialogPage. + */ + public void createControl(Composite parent) { + Composite composite= new Composite(parent, SWT.NONE); + + MGridLayout layout= new MGridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 5; + layout.minimumWidth= 450; + layout.minimumHeight= 350; + layout.numColumns= 1; + composite.setLayout(layout); + + tabFolder = new TabFolder(composite, SWT.NONE); + tabFolder.setLayout(new TabFolderLayout()); + + MGridData gd= new MGridData(); + gd.horizontalAlignment= gd.FILL; + gd.grabExcessHorizontalSpace= true; + gd.verticalAlignment= gd.FILL; + gd.grabExcessVerticalSpace= true; + tabFolder.setLayoutData(gd); + + wizard.addTabItems(tabFolder); + + //tabFolder.addSelectionListener(new SelectionAdapter() { + // public void widgetSelected(SelectionEvent e) { + // //tabChanged(e.item); + // } + //}); + + setControl(composite); + } + + public void setComplete(boolean complete) { + setPageComplete(isPageComplete()); + } + + public TabFolder getTabFolder() { + return tabFolder; + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + IWizardTab[] items = wizard.getTabItems(); + for (int i = 0; i < items.length; i++) { + items[i].setVisible(visible); + } + } + + public boolean isPageComplete() { + IWizardTab[] items = wizard.getTabItems(); + for (int i = 0; i < items.length; i++) { + if (!(items[i].isValid())) + return false; + } + return true; + } + + public TabFolderPage(CProjectWizard wizard) { + super("CProjectWizardTabPage"); + this.wizard = wizard; + } +}