Where it started
Second semester, April 2021. We had a major OOP assignment and I needed to submit something substantial. So I built a graphics library from scratch WinAPI under the hood, compiled into a DLL, named Vain Engine. It handled colored text output, keyboard input, and basic UI elements rendered entirely in the Windows console.
The code quality was not something I'd brag about. It was written by someone who was still learning, under deadline pressure, with the only goal being: make it run. It ran. I submitted. Done.
I didn't think much about it after that. Just another assignment.
Then third semester arrived
We had another major assignment. This time a full application UI, database, real features. And since I already had Vain Engine sitting there, I figured: use what you have.
So I built Student-DBMS on top of it. A Student Database Management System running entirely in the Windows console. The UI had this very specific look to it ASCII borders, chunky drop shadows, a menu bar, labeled panels. It genuinely looked like software from the early 90s that someone forgot to turn off. But the features were real: add, search, modify, and delete records; backup and restore; even an integrity validator.
The application worked. But building the UI for it was a slow grind. In Vain Engine at that point, everything was manual. Every menu option had its own color entry. Every frame had its own coordinates, textures, and border attributes. Every separator line was declared individually. Nothing was abstracted, nothing was reusable. You just described everything from scratch, every time.
Here's what setting up just the main menu looked like:
int option_colors[] = {
atr::HIGHLIGHTED_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
atr::DEFAULT_OPTION_COLOR,
};
std::string options[] = {
" Add Record ",
" Modify Record ",
" Search Record ",
" Show Records ",
" Delete Record ",
" Options ",
" About "
};
frame_.set_frame(
Dimension(18, 40), Coordinate(9, 1),
atr::WINDOW_BORDER_TEXTURE,
atr::WINDOW_SURFACE_TEXTURE,
atr::WINDOW_BACKGROUND_COLOR,
atr::WINDOW_SHADOW
);
label_.set_label("STUDENT DATABASE MANAGEMENT SYSTEM",
Coordinate(12, 4), atr::WINDOW_LABEL_COLOR, false);
Line separator_header = Line(38, Type.HORIZONTAL, 10, 5,
atr::WINDOW_FOOTER_LABEL_COLOR);
separator_header.Render();
selected_option = vertical_menu_.set_menu(
options, option_colors, TOTAL_OPTIONS,
Coordinate(14, 8),
Theme(atr::DEFAULT_OPTION_COLOR, atr::HIGHLIGHTED_OPTION_COLOR),
Control(UP, DOWN),
&status_lock, atr::BEEP, atr::SCROLL
);
Every screen in the application was built this way. Not just the menu every form, every panel, every labeled section. You repeat that whole ritual for each one. By the time the semester ended I had a working DBMS and a very strong opinion: the next time I touch this library, there's going to be a proper abstraction layer on top of it. No more raw coordinate arrays. No more specifying border textures by hand. Something that actually lets you think about the UI instead of the plumbing.
I had the whole winter break ahead of me. And I knew exactly what I was going to do with it.
The winter project
I spent that break building Menus a proper TUI component library sitting on top of Vain Engine. Vertical menus, horizontal menus, frames, drop shadows, a theme system. Real components with a real API, not raw attribute arrays passed into a function that expected you to know the internal layout.
The same menu that used to take forty-something lines became this:
const Color DEFAULT = eng::Color.BRIGHT_WHITE_BLACK;
const Color HIGHLIGHT = eng::Color.BRIGHT_BLUE_BRIGHT_WHITE;
std::unique_ptr<Menu> v_menu(new VerticalMenu({
{" Add Record ", HIGHLIGHT},
{" Modify Record ", DEFAULT},
{" Search Record ", DEFAULT},
{" Show Records ", DEFAULT},
{" Delete Record ", DEFAULT},
},
Coordinate(0, 0)
));
v_menu->setTheme(Theme(DEFAULT, HIGHLIGHT));
for (;;) {
while (!v_menu->isItemSelected()) {
v_menu->render();
}
v_menu->restart();
switch (v_menu->getItemPosition()) {
case 1: /* add record */ break;
case 2: /* modify record */ break;
case 3: /* search record */ break;
}
}

Frames with shadows went from a ten-step setup to five lines:
std::unique_ptr<Window> frame(new Frame(
Dimension(10, 30), Coordinate(3, 5)
));
frame->enableShadow(true);
frame->render();

I documented everything. Wrote a demo project to validate the components actually worked together. Cleaned up the repo. The Borland aesthetic was still there that was the point, that was the charm but now there was a real API underneath it. Anything that used to take an hour of setup would take ten minutes.
I remember wrapping it up and thinking: okay. Next semester is going to be different. Whatever C++ assignment shows up, I'm walking in prepared. I've already done the boring part. I just have to show up and build the actual thing.
4th semester
There was no C++ in 4th semester.