Продолжение статьи “Давайте дружить таблицами”

Три самые популярные кнопки в приложениях, создаваемых в среде разработки My Visual Dtabase, – это кнопки редактирования табличных данных: добавление, изменение и удаление записи. Обычно они находятся рядом с каждой таблицей, которую пользователь намеревается редактировать. Их функциональность определяется визуальными настройками, а создание занимает несколько секунд. Но в нашем приложении кнопок редактирования всего три, поэтому они будут не обычными, а “богатырскими”. Такие кнопки будут легко справляться со всеми таблицами приложения.

Располагаются эти кнопки на главной форме (1) и имеют традиционные названия и картинки (2). Но на этом их сходство со стандартными кнопками заканчивается, так как вся их сила заключена в скриптах. А сила скриптов – в соглашениях, которые необходимо соблюдать при наименовании форм приложения.

Соглашения

Соглашения – это правила, которые устанавливает разработчик для самого себя. Это очень полезная практика, которая позволяет писать эффективный код. Подробно об этой технике и различных примерах её использования написано в моей книге “Визуальное программирование”, глава 12. Выгодное соглашение.

Ниже представлены соглашения, которые помогли в составлении эффективного кода для кнопок редактирования.

Названия для форм табличного представления

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

frm<название таблицы>[_<суффикс>]

Например, в нашем приложении в таблице classType хранятся различные сведения, отображаемые различными формами: данные о типах (frmClassType_TypeList) и классах, а классы представлены как в виде списка (frmClassType_List), так и в виде дерева (frmClassType_Tree).

Названия для форм редактирования

Название формы редактирования состоит из префикса efm и названия таблицы, для редактирования которой предназначена данная форма.

efm<название таблицы>

Скрипты

Добавление новой записи использует метод формы NewRecord(). В качестве первого параметра в него передаётся название таблицы.

Примечание. Второй параметр используется при создании дочерних записей в древовидной структуре, но требует наличия на форме редактирования компонента с определенными настройками. В нашем приложении будет использована другая технология добавления в дерево.
procedure frmMain_btnNew_OnClick (Sender: TObject; var Cancel: boolean);
// добавлдение
var
  tmpID: integer;
  tmpTableName: string;
  tmpEditForm:TAForm;
  tmpForm:TAForm;
begin
  // если раскрыта вкладка с примером, то создаём пример
  if frmMain.pgcMain.ActivePage = frmMain.tshExample then
  begin
    efmExample.NewRecord('example');
  end
  else // если раскрыта вкладка навигатора и пользователь выделил таблицу, то создаем запись в таблице
  if (frmMain.pgcMain.ActivePage = frmMain.tshNavigation) and (ActiveGrid <> nil) then
  begin
    // определяем имя редактируемой таблицы, испльзуя соглашение по наименованию форм
    // <frm><имя таблицы>[_<суффикс>]
    tmpTableName := Grid_GetTableName(ActiveGrid);
    // используем соглашение для формы редактирования:
    // форма редектровани называется по шаблону:
    // <efm><название таблицы>
    tmpEditForm := App_GetFormByName('efm'+tmpTableName);
    CForm(ActiveGrid,tmpForm);
    // некторые таблицы зависят от главных, поэтому нужна проверка
    if not Form_CheckMasterForm(tmpForm.Name) then
      ShowHint(ActiveGrid,'Выберите запись в главной таблице')
    else
      // открываем форму редактирования
      tmpEditForm.NewRecord(tmpTableName);
  end;
end;

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

procedure frmMain_btnEdit_OnClick (Sender: TObject; var Cancel: boolean);
// редактирование
var
  tmpID: integer;
  tmpTableName: string;
  tmpEditForm:TAForm;
begin
  if frmMain.pgcMain.ActivePage = frmMain.tshExample then
  begin
    if IDExample <> -1 then
    begin
      efmExample.ShowRecord('example',IDExample);
      LoadExample;
    end;
  end
  else
  if frmMain.pgcMain.ActivePage = frmMain.tshNavigation then
  begin
    tmpID := ActiveGrid.dbItemID;
    tmpTableName := Grid_GetTableName(ActiveGrid);
    if tmpID = -1 then
      ShowHint(ActiveGrid,'Выберите запись')
    else
    begin
      // используем соглашение:
      // форма редектровани называется по шаблону:
      // <efm><название таблицы>
      tmpEditForm := App_GetFormByName('efm'+tmpTableName);
      if tmpEditForm<>nil then
        tmpEditForm.ShowRecord(tmpTableName, tmpID );
    end;
  end;
end;

Удаление выглядит аналогично редактированию, но использует в своей работе SQL команду DELETE:

procedure frmMain_btnDelete_OnClick (Sender: TObject; var Cancel: boolean);
var
  tmpID: string;
  tmpTableName: string;
begin
  if frmMain.pgcMain.ActivePage = frmMain.tshExample then
  begin
    if IDExample <> -1 then
      if MessageBox( 'Удалить пример?', 'Удаление', MB_YESNO + MB_ICONWARNING ) = mrYes then
      begin
        SQLExecute('delete from example where id = '+IntToStr(IDExample) );
        UpdateDatabase('example');
      end;
  end
  else
  if (frmMain.pgcMain.ActivePage = frmMain.tshNavigation) and (ActiveGrid<>nil) then
  begin
    tmpID := IntToStr(ActiveGrid.dbItemID);
    tmpTableName := Grid_GetTableName(ActiveGrid);
    if tmpID = '-1' then
      ShowHint(ActiveGrid,'Выберите запись')
    else
    if MessageBox( 'Удалить запись?', 'Удаление', MB_YESNO + MB_ICONWARNING ) = mrYes then
    begin
      SQLExecute('delete from '+tmpTableName+' where id = '+tmpID );
      UpdateDatabase(tmpTableName);
    end;
  end;
end;

Вышеуказанные процедуры используют ключевую функцию Grid_GetTableName(). Её реализация выглядит очень лаконично.

function Grid_GetTableName( AGrid: TdbStringGridEx ):string;
// возвращает имя таблицы
var
  tmpForm:TAForm;
begin
  // используем соглашение по наименованию формы:
  // <frm><имя таблицы>[_<суффикс>]
  // то есть может быть несколько форм с табличным представлением для одной таблицы,
  // они должны различаться суффиксом
  CForm(AGrid,tmpForm);
  Result := DeleteSuffix(DeleteClassName(tmpForm.Name));
end;
Примечание. При попытке создать аналогичную функцию без использования соглашений о наименовании, я обнаружил ошибку в работе MVDB, а именно: у компонента TdbTreeView в свойстве dbGeneralTable отсутствует название таблицы, которое он отображает. Эта ошибка помешала создать универсальную функцию, которая бы работала как для таблиц, так и для дерева.

А вот ещё одна используемая в процедурах “богатырских” кнопок полезная функция, которая возвращает форму приложения по имени:

function App_GetFormByName(AName: string): TAForm;
// получение формы по названию
var
  tmpForm: TAForm;
  i: integer;
begin
  AName := UpperCase(AName);
  for i := 0 to Screen.FormCount - 1 do
  begin
    Result := TAForm(Screen.Forms[i]);
    if UpperCase(Result.Name) = AName then
      exit;
  end;
  Result := nil;
end;

Продолжение “Гений кроется в деталях”

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *