Critique of C Code Snippet: Handling Button1 Press During Edit Dialog
/* button1 click to select another instance while edit prop dialog open */if(button==Button1 && xctx->semaphore >= 2) { if(tcleval("winfo exists .dialog.textinput")[0] == '1') { /* proc text_line */ tcleval(".dialog.f1.b1 invoke"); return; } else if(tcleval("winfo exists .dialog.txt")[0] == '1') { /* proc enter_text */ tcleval(".dialog.buttons.ok invoke"); return; } else if(state==0 && tclgetvar("edit_symbol_prop_new_sel")[0]) { tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke"); /* invoke 'OK' of edit prop dialog */ } else if((state & ShiftMask) && tclgetvar("edit_symbol_prop_new_sel")[0]) { select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); tclsetvar("preserve_unchanged_attrs", "1"); rebuild_selected_array(); }}
✅ What Works Well
- Functionally Correct: It correctly distinguishes between various UI dialog contexts and responds appropriately.
- UI-Sensitive Logic: It properly accounts for Shift key usage and application state (`semaphore`).
❗ Issues & Suggestions
1. Too Many Inline TCL Calls
Calling tcleval("winfo exists ...") multiple times is inefficient and clutters readability.
// Suggestion:
int text_input_exists = tcleval("winfo exists .dialog.textinput")[0] == '1';
2. Hardcoded String Literals
These are fragile and error-prone. Use #define for better readability and maintainability.
#define DIALOG_TEXTINPUT_CHECK "winfo exists .dialog.textinput"
#define DIALOG_OK_INVOKE ".dialog.f1.b1 invoke"
#define SYMBOL_PROP_VAR "edit_symbol_prop_new_sel"
3. Dense Conditional Chain
All logic is packed into a single if block. It's difficult to scan and should be factored into a helper function.
void handle_edit_dialog_selection(int state) {
if (dialog_exists(".dialog.textinput")) {
tcleval(".dialog.f1.b1 invoke");
return;
}
if (dialog_exists(".dialog.txt")) {
tcleval(".dialog.buttons.ok invoke");
return;
}
const char *sel_flag = tclgetvar("edit_symbol_prop_new_sel");
if (state == 0 && sel_flag[0]) {
tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke");
} else if ((state & ShiftMask) && sel_flag[0]) {
select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL);
tclsetvar("preserve_unchanged_attrs", "1");
rebuild_selected_array();
}
}
Then the main logic becomes:
if (button == Button1 && xctx->semaphore >= 2) {
handle_edit_dialog_selection(state);
}
4. No Feedback or Logging
If none of the dialog paths are valid, the code silently continues. A debug log can help during maintenance.
🧾 Summary
| Aspect | Evaluation | Notes |
|---|---|---|
| Functionality | ✅ Solid | Handles all expected dialog interactions |
| Performance | ⚠️ Medium | Redundant calls to tcleval |
| Readability | ⚠️ Poor | Hardcoded strings and dense logic |
| Maintainability | ❌ Weak | Needs function separation and better naming |
✅ Final Suggestion
Refactor into a dedicated function and avoid repeated logic. Add debug messages for unexpected states.
No comments:
Post a Comment